前言:这是由本人二刷该项目,结合老师笔记的个人总结,本博客梳理项目核心内容,助力大家学习苍穹外卖项目。全套资料位于文章末尾,自取即可🌸
思维导图
1. 苍穹外卖项目简介
本项目(苍穹外卖)是专门为餐饮企业(餐厅、饭店)定制的一款软件产品,包括系统管理后台和小程序端应用两部分。
系统管理后台:主要提供给餐饮企业内部员工使用,可以对餐厅的分类、菜品、套餐、订单、员工等进行管理维护,对餐厅的各类数据进行统计,同时也可进行来单语音播报功能。
小程序端:主要提供给消费者使用,可以在线浏览菜品、添加购物车、下单、支付、催单等。
2. 苍穹外卖项目详细介绍
2.1 项目介绍
我们将从项目简介、产品原型、技术选型三个方面来了解苍穹外卖这个项目。
接下来,通过功能架构图来展示管理端和用户端的具体业务功能模块。
1). 管理端功能
员工登录/退出 , 员工信息管理 , 分类管理 , 菜品管理 , 套餐管理 , 菜品口味管理 , 订单管理 ,数据统计,来单提醒。
2). 用户端功能
微信登录 , 收件人地址管理 , 用户历史订单查询 , 菜品规格查询 , 购物车功能 , 下单 , 支付、分类及菜品浏览。
2.2 产品原型
产品原型,用于展示项目的业务功能,一般由产品经理进行设计。
注意事项:产品原型主要用于展示项目的功能,并不是最终的页面效果。
以下是两份产品原型。
管理端原型图:
用户端原型图:
1). 管理端
餐饮企业内部员工使用。 主要功能有:
| 模块 | 描述 |
|---|---|
| 登录/退出 | 内部员工必须登录后,才可以访问系统管理后台 |
| 员工管理 | 管理员可以在系统后台对员工信息进行管理,包含查询、新增、编辑、禁用等功能 |
| 分类管理 | 主要对当前餐厅经营的 菜品分类 或 套餐分类 进行管理维护, 包含查询、新增、修改、删除等功能 |
| 菜品管理 | 主要维护各个分类下的菜品信息,包含查询、新增、修改、删除、启售、停售等功能 |
| 套餐管理 | 主要维护当前餐厅中的套餐信息,包含查询、新增、修改、删除、启售、停售等功能 |
| 订单管理 | 主要维护用户在移动端下的订单信息,包含查询、取消、派送、完成,以及订单报表下载等功能 |
| 数据统计 | 主要完成对餐厅的各类数据统计,如营业额、用户数量、订单等 |
2). 用户端
移动端应用主要提供给消费者使用。主要功能有:
| 模块 | 描述 |
|---|---|
| 登录/退出 | 用户需要通过微信授权后登录使用小程序进行点餐 |
| 点餐-菜单 | 在点餐界面需要展示出菜品分类/套餐分类, 并根据当前选择的分类加载其中的菜品信息, 供用户查询选择 |
| 点餐-购物车 | 用户选中的菜品就会加入用户的购物车, 主要包含 查询购物车、加入购物车、删除购物车、清空购物车等功能 |
| 订单支付 | 用户选完菜品/套餐后, 可以对购物车菜品进行结算支付, 这时就需要进行订单的支付 |
| 个人信息 | 在个人中心页面中会展示当前用户的基本信息, 用户可以管理收货地址, 也可以查询历史订单数据 |
2.3技术选型(老师总结)
关于本项目的技术选型, 我们将会从 用户层、网关层、应用层、数据层 这几个方面进行介绍,主要用于展示项目中使用到的技术框架和中间件等。
1). 用户层
本项目中在构建系统管理后台的前端页面,我们会用到H5、Vue.js、ElementUI、apache echarts(展示图表)等技术。而在构建移动端应用时,我们会使用到微信小程序。
2). 网关层
Nginx是一个服务器,主要用来作为Http服务器,部署静态资源,访问性能高。在Nginx中还有两个比较重要的作用: 反向代理和负载均衡, 在进行项目部署时,要实现Tomcat的负载均衡,就可以通过Nginx来实现。
3). 应用层
| 技术 / 框架 | 说明 |
|---|---|
| SpringBoot | 快速构建 Spring 项目,简化 Spring 项目的开发。 |
| SpringMVC | Spring 框架的一个模块,与 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请求,获取对应的响应结果。
3. 开发环境搭建
开发环境搭建主要包含前端环境和后端环境两部分。作为服务端开发工程师, 我们课程学习的重心应该放在后端的业务代码上, 前端的页面我们只需要导入资料中的nginx, 前端页面的代码我们只需要能看懂即可。
3.1 前端环境搭建
1). 前端工程基于 nginx
从资料中找到前端运行环境的nginx,移动到非中文目录下。
sky目录中存放了管理端的前端资源,具体如下:
2). 启动nginx,访问测试
双击 nginx.exe 即可启动 nginx 服务,访问端口号为 80
3.2 后端环境搭建
3.2.1 熟悉项目结构
1). 从当天资料中找到后端初始工程:
2). 用 IDEA 打开初始工程,了解项目的整体结构:
对工程的每个模块作用说明:
| 序号 | 名称 | 说明 |
|---|---|---|
| 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 | 启动类 |
3.2.2 Git版本控制
将本地文件推送到Git远程仓库
Guo-chang16/sky-take-out1https://github.com/Guo-chang16/sky-take-out1
3.2.3 数据库环境搭建
1.从资料中找到sky.sql
2.执行sky.sql文件
每张表的说明:
| 序号 | 表名 | 中文名 |
|---|---|---|
| 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 | 订单明细表 |
3.2.4 前后端联调
实现思路:
1.Controller层
在sky-server模块中,com.sky.controller.admin.EmployeeController
//小知识点 //DTO中包含对应的前端传过来的json格式的数据 @RequestBody EmployeeLoginDTO employeeLoginDTO/** * 登录 * * @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); }3.3 完善登录功能
解决思路:
将密码加密后存储,提高安全性
// TODO 后期需要进行md5加密,然后再进行比对 password = DigestUtils.md5DigestAsHex(password.getBytes());4. 导入接口文档
4.1 前后端分离开发流程
第一步:定义接口,确定接口的路径、请求方式、传入参数、返回参数。
第二步:前端开发人员和后端开发人员并行开发。
第三步:前后端人员进行连调测试。
第四步:提交给测试人员进行最终测试。
5. Swagger
5.1 介绍
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。它的主要作用是:
接口的文档在线自动生成
功能测试
5.2 使用步骤
1.导入 knife4j 的maven坐标
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> </dependency>2.在配置类中加入 knife4j 相关配置
/** * 通过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; } 3.设置静态资源映射,否则接口文档页面无法访问
/** * 设置静态资源映射 * @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/"); }4.访问测试
思考:通过 Swagger 就可以生成接口文档,那么我们就不需要 Yapi 了?
1、Yapi 是设计阶段使用的工具,管理和维护接口
2、Swagger 在开发阶段使用的框架,帮助后端开发人员做后端的接口测试
5.3 常用注解
通过注解可以控制生成的接口文档,使接口文档拥有更好的可读性,常用注解如下:
| 注解 | 说明 |
|---|---|
| @Api | 用在类上,例如Controller,表示对类的说明 |
| @ApiModel | 用在类上,例如entity、DTO、VO |
| @ApiModelProperty | 用在属性上,描述属性信息 |
| @ApiOperation | 用在方法上,例如Controller的方法,说明方法的用途、作用 |
启动服务:访问http://localhost:8080/doc.html
至此,开启学习苍穹外卖的旅程!🎉🎉🎉
《苍穹外卖》全套资料获取地方,有需要的自取哈
https://pan.baidu.com/s/13ROdNBym3t-I-TcrT8hisw
提取码: wind