首页 > 其他分享 >苍穹外卖-第一章项目介绍

苍穹外卖-第一章项目介绍

时间:2023-09-30 22:38:10浏览次数:41  
标签:8080 com sky server 外卖 employee import 第一章 苍穹

1. 苍穹外卖项目介绍

1.1 项目介绍

1)管理端功能

员工登录/退出 , 员工信息管理 , 分类管理 , 菜品管理 , 套餐管理 , 菜品口味管理 , 订单管理 ,数据统计,来单提醒。

2)用户端功能

微信登录 , 收件人地址管理 , 用户历史订单查询 , 菜品规格查询 , 购物车功能 , 下单 , 支付、分类及菜品浏览。

1.2 产品原型

1)管理端

餐饮企业内部员工使用。 主要功能有:

模块 描述
登录/退出 内部员工必须登录后,才可以访问系统管理后台
员工管理 管理员可以在系统后台对员工信息进行管理,包含查询、新增、编辑、禁用等功能
分类管理 主要对当前餐厅经营的 菜品分类 或 套餐分类 进行管理维护, 包含查询、新增、修改、删除等功能
菜品管理 主要维护各个分类下的菜品信息,包含查询、新增、修改、删除、启售、停售等功能
套餐管理 主要维护当前餐厅中的套餐信息,包含查询、新增、修改、删除、启售、停售等功能
订单管理 主要维护用户在移动端下的订单信息,包含查询、取消、派送、完成,以及订单报表下载等功能
数据统计 主要完成对餐厅的各类数据统计,如营业额、用户数量、订单等

2)用户端

移动端应用主要提供给消费者使用。主要功能有:

模块 描述
登录/退出 用户需要通过微信授权后登录使用小程序进行点餐
点餐-菜单 在点餐界面需要展示出菜品分类/套餐分类, 并根据当前选择的分类加载其中的菜品信息, 供用户查询选择
点餐-购物车 用户选中的菜品就会加入用户的购物车, 主要包含 查询购物车、加入购物车、删除购物车、清空购物车等功能
订单支付 用户选完菜品/套餐后, 可以对购物车菜品进行结算支付, 这时就需要进行订单的支付
个人信息 在个人中心页面中会展示当前用户的基本信息, 用户可以管理收货地址, 也可以查询历史订单数据

1.3 技术选型

关于本项目的技术选型, 我们将会从 用户层、网关层、应用层、数据层 这几个方面进行介绍,主要用于展示项目中使用到的技术框架和中间件等。

  • 用户层 node.js VUE.js ElementUI 微信小程序 apache echarts
  • 网关层 Nginx
  • 应用层 SpringBoot SpringMVC SpringTask SpringCache JWT 阿里云OSS httpclient Swagger POI WebSocket
  • 数据层 MySQL Redis mybatis
  • 工具 Git maven Junit postman pagehelper springdataredis

1)用户层
后台的前端页面用到H5、Vue.js、ElementUI、apache echarts(展示图表)等技术。移动端应用使用到微信小程序。

2)网关层
Nginx是一个服务器,主要用来作为Http服务器,部署静态资源,访问性能高。在Nginx中还有两个比较重要的作用: 反向代理和负载均衡, 在进行项目部署时,要实现Tomcat的负载均衡,就可以通过Nginx来实现。

3)应用层

  • SpringBoot: 快速构建Spring项目, 采用 "约定优于配置" 的思想, 简化Spring项目的配置开发。
  • SpringMVC:SpringMVC是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合,可以无缝集成。
  • Spring Task: 由Spring提供的定时任务框架。
  • httpclient: 主要实现了对http请求的发送。
  • Spring Cache: 由Spring提供的数据缓存框架
  • JWT: 用于对应用程序上的用户进行身份验证的标记。
  • 阿里云OSS: 对象存储服务,在项目中主要存储文件,如图片等。
  • Swagger: 可以自动的帮助开发人员生成接口文档,并对接口进行测试。
  • POI: 封装了对Excel表格的常用操作。
  • WebSocket: 一种通信网络协议,使客户端和服务器之间的数据交换更加简单,用于项目的来单、催单功能实现。

4)数据层

  • MySQL: 关系型数据库, 本项目的核心业务数据都会采用MySQL进行存储。
  • Redis: 基于key-value格式存储的内存数据库, 访问速度快, 经常使用它做缓存。
  • Mybatis: 本项目持久层将会使用Mybatis开发。
  • pagehelper: 分页插件。
  • spring data redis: 简化java代码操作Redis的API。

5)工具

  • git: 版本控制工具, 在团队协作中, 使用该工具对项目中的代码进行管理。
  • maven: 项目构建工具。
  • junit:单元测试工具,开发人员功能实现完毕后,需要通过junit对功能进行单元测试。
  • postman: 接口测工具,模拟用户发起的各类HTTP请求,获取对应的响应结果。

2. 开发环境搭建

2.1 熟悉项目结构

对工程的每个模块作用说明:

序号 名称 说明
1 sky-take-out maven父工程,统一管理依赖版本,聚合其他子模块
2 sky-common 子模块,存放公共类,例如:工具类、常量类、异常类等
3 sky-pojo 子模块,存放实体类、VO、DTO等
4 sky-server 子模块,后端服务,存放配置文件、Controller、Service、Mapper等
  • sky-common: 模块中存放的是一些公共类,可以供其他模块使用

    分析sky-common模块的每个包的作用:

    名称 说明
    constant 存放相关常量类
    context 存放上下文类
    enumeration 项目的枚举类存储
    exception 存放自定义异常类
    json 处理json转换的类
    properties 存放SpringBoot相关的配置属性类
    result 返回结果类的封装
    utils 常用工具类
  • sky-pojo: 模块中存放的是一些 entity、DTO、VO

    分析sky-pojo模块的每个包的作用:

    名称 说明
    Entity 实体,通常和数据库中的表对应
    DTO 数据传输对象,通常用于程序中各层之间传递数据
    VO 视图对象,为前端展示数据提供的对象
    POJO 普通Java对象,只有属性和对应的getter和setter
  • sky-server: 模块中存放的是 配置文件、配置类、拦截器、controller、service、mapper、启动类等

    分析sky-server模块的每个包的作用:

    名称 说明
    config 存放配置类
    controller 存放controller类
    interceptor 存放拦截器类
    mapper 存放mapper接口
    service 存放service类
    SkyApplication 启动类

2.2 数据库环境搭建

序号 表名 中文名
1 employee 员工表
2 category 分类表
3 dish 菜品表
4 dish_flavor 菜品口味表
5 setmeal 套餐表
6 setmeal_dish 套餐菜品关系表
7 user 用户表
8 address_book 地址表
9 shopping_cart 购物车表
10 orders 订单表
11 order_detail 订单明细表

2.3 前后端联调

1.Controller层

在sky-server模块中,com.sky.controller.admin.EmployeeController

/**
     * 登录
     *
     * @param employeeLoginDTO
     * @return
     */
    @PostMapping("/login")
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
        log.info("员工登录:{}", employeeLoginDTO);
		//调用service方法查询数据库
        Employee employee = employeeService.login(employeeLoginDTO);

        //登录成功后,生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
                .id(employee.getId())
                .userName(employee.getUsername())
                .name(employee.getName())
                .token(token)
                .build();

        return Result.success(employeeLoginVO);
    }

2.Service层

在sky-server模块中,com.sky.service.impl.EmployeeServiceImpl

/**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

3.Mapper层

在sky-server模块中,com.sky.mapper.EmployeeMapper

package com.sky.mapper;

import com.sky.entity.Employee;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface EmployeeMapper {

    /**
     * 根据用户名查询员工
     * @param username
     * @return
     */
    @Select("select * from employee where username = #{username}")
    Employee getByUsername(String username);

}

注:可以通过断点调试跟踪后端程序的执行过程

2.4 nginx反向代理和负载均衡

对登录功能测试完毕后,接下来一个问题:前端发送的请求,是如何请求到后端服务的?

前端请求地址:http://localhost/api/employee/login
后端接口地址:http://localhost:8080/admin/employee/login
很明显,两个地址不一致,那是如何请求到后端服务的呢?

1)nginx反向代理

nginx 反向代理,就是将前端发送的动态请求由 nginx 转发到后端服务器

那为什么不直接通过浏览器直接请求后台服务端,需要通过nginx反向代理呢?

nginx 反向代理的好处:

  • 提高访问速度
    因为nginx本身可以进行缓存,如果访问的同一接口,并且做了数据缓存,nginx就直接可把数据返回,不需要真正地访问服务端,从而提高访问速度。

  • 进行负载均衡
    所谓负载均衡,就是把大量的请求按照我们指定的方式均衡的分配给集群中的每台服务器。

  • 保证后端服务安全
    因为一般后台服务地址不会暴露,所以使用浏览器不能直接访问,可以把nginx作为请求访问的入口,请求到达nginx后转发到具体的服务中,从而保证后端服务的安全。

nginx 反向代理的配置方式:

server{
    listen 80;
    server_name localhost;

    location /api/{
        proxy_pass http://localhost:8080/admin/; #反向代理
    }
}

proxy_pass:该指令是用来设置代理服务器的地址,可以是主机名称,IP地址加端口号等形式。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/../..这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://localhost:8080/admin/上来。

接下来,进到nginx-1.20.2\conf,打开nginx配置

# 反向代理,处理管理端发送的请求
location /api/ {
	proxy_pass   http://localhost:8080/admin/;
    #proxy_pass   http://webservers/admin/;
}

当在访问http://localhost/api/employee/login,nginx接收到请求后转到http://localhost:8080/admin/,故最终的请求地址为http://localhost:8080/admin/employee/login,和后台服务的访问地址一致

2)nginx 负载均衡

当如果服务以集群的方式进行部署时,那nginx在转发请求到服务器时就需要做相应的负载均衡。其实,负载均衡从本质上来说也是基于反向代理来实现的,最终都是转发请求。

nginx 负载均衡的配置方式:

upstream webservers{
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}
server{
    listen 80;
    server_name localhost;

    location /api/{
        proxy_pass http://webservers/admin;#负载均衡
    }
}

upstream:如果代理服务器是一组服务器的话,我们可以使用upstream指令配置后端服务器组。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/../..这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://webservers/admin,根据webservers名称找到一组服务器,根据设置的负载均衡策略(默认是轮询)转发到具体的服务器。

注:upstream后面的名称可自定义,但要上下保持一致。

nginx 负载均衡策略:

名称 说明
轮询 默认方式
weight 权重方式,默认为1,权重越高,被分配的客户端请求就越多
ip_hash 依据ip分配方式,这样每个访客可以固定访问一个后端服务
least_conn 依据最少连接方式,把请求优先分配给连接数少的后端服务
url_hash 依据url分配方式,这样相同的url会被分配到同一个后端服务
fair 依据响应时间方式,响应时间短的服务将会被优先分配

具体配置方式:

轮询:

upstream webservers{
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

weight:

upstream webservers{
    server 192.168.100.128:8080 weight=90;
    server 192.168.100.129:8080 weight=10;
}

ip_hash:

upstream webservers{
    ip_hash;
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

least_conn:

upstream webservers{
    least_conn;
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

url_hash:

upstream webservers{
    hash &request_uri;
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

fair:

upstream webservers{
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
    fair;
}

3. 完善登录功能

问题:员工表中的密码是明文存储,安全性太低。
解决思路:

  1. 将密码加密后存储,提高安全性
  2. 使用MD5加密方式对明文密码加密

实现步骤:

  1. 修改数据库中明文密码,改为MD5加密后的密文
    打开employee表,修改密码

  2. 修改Java代码,前端提交的密码进行MD5加密后再跟数据库中密码比对
    打开EmployeeServiceImpl.java,修改比对密码

   /**
        * 员工登录
        *
        * @param employeeLoginDTO
        * @return
        */
       public Employee login(EmployeeLoginDTO employeeLoginDTO) {
           //1、根据用户名查询数据库中的数据
           //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
           //.......
           //密码比对
           // TODO 后期需要进行md5加密,然后再进行比对
           password = DigestUtils.md5DigestAsHex(password.getBytes());
           if (!password.equals(employee.getPassword())) {
               //密码错误
               throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
           }
           //3、返回实体对象
           return employee;
       }

4. Swagger

4.1 介绍

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(https://swagger.io/)。 它的主要作用是:

  1. 使得前后端分离开发更加方便,有利于团队协作
  2. 接口的文档在线自动生成,降低后端开发人员编写接口文档的负担
  3. 功能测试

Spring已经将Swagger纳入自身的标准,建立了Spring-swagger项目,现在叫Springfox。通过在项目中引入Springfox ,即可非常简单快捷的使用Swagger。

knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!

目前,一般都使用knife4j框架。

4.2 使用步骤

  1. 导入 knife4j 的maven坐标

在pom.xml中添加依赖

   <dependency>
      <groupId>com.github.xiaoymin</groupId>
      <artifactId>knife4j-spring-boot-starter</artifactId>
   </dependency>
  1. 在配置类中加入 knife4j 相关配置

WebMvcConfiguration.java

   /**
        * 通过knife4j生成接口文档
        * @return
   */
       @Bean
       public Docket docket() {
           ApiInfo apiInfo = new ApiInfoBuilder()
                   .title("苍穹外卖项目接口文档")
                   .version("2.0")
                   .description("苍穹外卖项目接口文档")
                   .build();
           Docket docket = new Docket(DocumentationType.SWAGGER_2)
                   .apiInfo(apiInfo)
                   .select()
                   .apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
                   .paths(PathSelectors.any())
                   .build();
           return docket;
       }
  1. 设置静态资源映射,否则接口文档页面无法访问

WebMvcConfiguration.java

   /**
        * 设置静态资源映射
        * @param registry
   */
   protected void addResourceHandlers(ResourceHandlerRegistry registry) {
           registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
           registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
   }
  1. 访问测试

接口文档访问路径为 http://ip:port/doc.html ---> http://localhost:8080/doc.html

4.3 常用注解

通过注解可以控制生成的接口文档,使接口文档拥有更好的可读性,常用注解如下:

注解 说明
@Api 用在类上,例如Controller,表示对类的说明
@ApiModel 用在类上,例如entity、DTO、VO
@ApiModelProperty 用在属性上,描述属性信息
@ApiOperation 用在方法上,例如Controller的方法,说明方法的用途、作用

接下来,使用上述注解,生成可读性更好的接口文档

在sky-pojo模块中
EmployeeLoginDTO.java

package com.sky.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

@Data
@ApiModel(description = "员工登录时传递的数据模型")
public class EmployeeLoginDTO implements Serializable {

    @ApiModelProperty("用户名")
    private String username;

    @ApiModelProperty("密码")
    private String password;

}

EmployeeLoginVo.java

package com.sky.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "员工登录返回的数据格式")
public class EmployeeLoginVO implements Serializable {

    @ApiModelProperty("主键值")
    private Long id;

    @ApiModelProperty("用户名")
    private String userName;

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("jwt令牌")
    private String token;

}

在sky-server模块中

EmployeeController.java

package com.sky.controller.admin;

import com.sky.constant.JwtClaimsConstant;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.entity.Employee;
import com.sky.properties.JwtProperties;
import com.sky.result.Result;
import com.sky.service.EmployeeService;
import com.sky.utils.JwtUtil;
import com.sky.vo.EmployeeLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 员工管理
 */
@RestController
@RequestMapping("/admin/employee")
@Slf4j
@Api(tags = "员工相关接口")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 登录
     *
     * @param employeeLoginDTO
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "员工登录")
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) 	{
        //
    }

    /**
     * 退出
     *
     * @return
     */
    @PostMapping("/logout")
    @ApiOperation("员工退出")
    public Result<String> logout() {
        return Result.success();
    }

}

启动服务:访问http://localhost:8080/doc.html

标签:8080,com,sky,server,外卖,employee,import,第一章,苍穹
From: https://www.cnblogs.com/szlsay/p/17737747.html

相关文章

  • 苍穹外卖-第二章员工管理
    1.新增员工1.1需求分析和设计1.1.1产品原型一般在做需求分析时,往往都是对照着产品原型进行分析,因为产品原型比较直观,便于我们理解业务。后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。当填写完表单信息,点击"保存"按钮后,会提交该表单的数据到服务端,在......
  • 外卖配送系统开发指南:打造高效、智能的外卖服务
    随着外卖市场的蓬勃发展,餐厅和外卖平台需要不断提高外卖服务的效率和智能性,以满足不断增长的需求。在本文中,我们将探讨如何开发一个高效、智能的外卖配送系统,同时提供一些关键代码示例来帮助您入门。环境准备在开始外卖配送系统的开发之前,您需要确保具备以下基本环境和工具:编程语言......
  • 第一章 计算机系统概述
    一.基本组成1.计算机包含四个主要的结构:处理器:控制计算机的操作,并执行数据处理的功能。当只有一个处理器时,被称为中央处理单元(cpu)内存:存储数据和程序。这种存储通常易失,关机时内存数据会丢失。磁盘存储器中的数据即使计算机系统关闭也会被保留。内存称为主存,硬盘为辅存......
  • 通过苍穹外卖学习分页查询
    ‍controller层/***员工分页查询*@paramemployeePageQueryDTO*@return*/@GetMapping("/page")@ApiOperation("员工分页查询")publicResult<PageResult>page(EmployeePageQueryDTOemployeePageQueryDTO){......
  • 外卖订餐系统:数字时代的美食点餐新体验
    在数字时代,外卖订餐系统已经成为现代生活的一部分。它不仅改变了我们点餐的方式,还为餐饮业带来了巨大的变革。本文将深入探讨外卖订餐系统的崭新世界,探讨它的发展历程、优势和未来趋势。从电话点餐到外卖订餐系统许多人还记得过去打电话点外卖的日子。您需要查找菜单、拨打电话、等......
  • MySQL进阶篇:第一章_一.五_MySQL存储引擎选择
    MySQL存储引擎选择在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据实际情况选择多种存储引擎进行组合。InnoDB:是Mysql的默认存储引擎,支持事务、外键。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作......
  • 开发同城O2O外卖系统源码:外卖跑腿小程序的核心功能
    随着移动互联网的快速发展,外卖行业迎来了巨大的机遇。O2O(Online to Offline)模式逐渐崭露头角,而同城外卖跑腿小程序成为了这一领域的热门选择。 第一部分:简介简单涞水,外卖跑腿平台是一种允许用户在同城范围内订购食物、货物或服务的应用程序。那么,想要开发一个同城O2O外卖系统,您......
  • 构建高效的同城O2O外卖系统APP:技术要点和最佳实践
    时下,消费者的需求不断演变,迫使外卖服务提供商不断改进其技术和服务。本文将讨论如何构建一个高效的同城O2O(Online-to-Offline)外卖系统APP,突出了关键的技术要点和最佳实践。一、用户界面设计 1.1 直观简单直观,以确保用户可以轻松地浏览菜单、下单和支付。使用易于理解的图标和符号......
  • 《流畅的Python》 读书笔记 230926(第一章后半部分)
    1.2如何使用特殊方法特殊方法的存在是为了被Python解释器调用的,你自己并不需要调用它们就是说通常你都应该用len(obj)而不是obj.__len()__,无论是系统预置的,还是你自己定义的类,交给Python,解释器会去调用你实现的__len()__然而如果是Python内置的类型,比如列表(list)、字符......
  • 外卖霸王餐系统 美团试吃系统 支持分销代理
    微客云免费提供外卖霸王餐系统,支持分站、运营商、商家后台、独立域名,自定义品牌,自主收款。想做霸王餐的可以参考下联系微客云。地址:微客云-淘宝客CMS,公众号,小程序,淘客APP,外卖返利CPS,私域电商系统分站后台演示: ......