瑞吉外卖总结

本文概述了黑马瑞吉外卖项目的背景,介绍了其定制的系统管理软件、使用的技术如Redis缓存、MySQL主从复制、前后端部署架构等,展示了项目在疫情期间的用户增长以及技术应对策略。
摘要由CSDN通过智能技术生成

黑马瑞吉外卖项目总结

1.1 项目背景

随着我国城镇和农村居民生活水平达到富裕和小康层次,消费在国民经济活动中的比重逐步加大,居民的餐饮消费逐渐从一日三餐的刚需升级到感受餐饮文化以及社交的重要方式,近年来我国餐饮业销售收入逐年攀升,2019年中国餐饮收入达4.67万亿元,较2018年增加了0.40万亿元,同比增长9.38%,受新冠肺炎疫情影响,2020年中国餐饮收入大幅下滑,随着国内疫情的有效控制,中国餐饮市场也逐渐复苏,2021年中国餐饮收入完成4.69万亿元,较2020年增加了0.74万亿元,同比增长18.64%。“新冠疫情”改变了人们的就餐习惯,对于病毒的心理障碍,更多人选择外卖的方式来就餐,截止2021年12月末中国网上外卖用户规模达54416万人,较2020年同期增加了12533万人,同比增长29.92%。“新冠疫情”改变了人们的就餐习惯,对于病毒的心理障碍,更多人选择外卖的方式来就餐,截止2021年12月末中国网上外卖用户规模达54416万人,较2020年同期增加了12533万人,同比增长29.92%。

1.2 项目介绍

本项目(瑞吉外卖)是专门为餐厅、饭店定制的一款软件产品,包括系统管理后台和移动端应用两部分。其中系统管理后台主要提供给餐饮内部员工使用,可以对餐厅的菜品、套餐、订单进行管理和维护。移动端应用主要提供给消费者使用,可以在线浏览菜品、添加购物车、下单等。

1.3 项目亮点

1、使用Redis进行缓存
当用户数量较多时,系统访问量大,频繁的访问数据库,数据库压力大,系统的性能下降,用户体验感差。因此使用Redis对数据进行缓存,从而减小数据库的压力,在数据更新时删除缓存,从而保证数据库和缓存的一致性,同时有效提高系统的性能和访问速度。

2、使用MySQL主从复制,进行读写分离
读和写数据的所有压力全都由一台数据库承担,压力大,数据库服务器磁盘损坏则数据丢失,单点故障。使用MySQL进行主从复制,主库(master)进行写操作(intsert update delete),从库(salve)进行读操作(select),从而减轻数据库负担,增大系统承受能力,提高系统性能。本项目使用Sharding-JDBC在程序中实现读写分离。

注:MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库目带的二进制日志功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制然后再解析日志并应用到自身,最终实现从库的数据和主库的数据保持一致。MySQL主从复制是MysQL数据库自带功能,无需借助第三方工具。

3、前后端分别部署,使用Nginx进行反向代理
前端页面部署到Nginx服务器中,后端代码部署到后端服务器中,使用Nginx对后端服务器进行反向代理,使用户只需要访问Nginx服务器便可获得后端服务器的服务(便于后期扩展集群,提高系统并发量)。

技术
SpringBoot+SSM 企业级项目
SSM=Spring+Spring MVC+MyBatis

nginx 是服务器,主要部署静态资源。前端请求nginx服务器,再分发到多个tomcat服务器。
Spring Session解决集群的session共享问题。
Swagger:前后端分离使用。
Redis:主要用作缓存。

展示
移动端:展示数据,消费者使用
+
后台管理:维护数据,餐饮企业使用

数据表

一个套餐是多个菜品的集合;
一个菜品有多个口味;
一个顾客可以同时把多个菜品和多个套餐放入购物车中。

slf4j

@sl4j是lombok提供的

功能开发:
员工管理

  1. 后台登录

登录时,以json格式将数据发送至后端

开启驼峰命名
id是雪花算法自动生成的

mp规范:

通用结果类 R
后端返给前端的响应结果

前端使用的是json数据

数据库存储的密码是加密过的
md5加密

错误时,前端展示

  1. 后台退出

  2. 完善登录

{}是占位符,将会显示逗号后面的内容

传给前端json数据

  1. 新增员工

账号设置了唯一的属性,添加相同账号时,数据库抛了异常

全局异常捕获:注解是xxx的类,异常是xxx时,就会被拦截处理
注解是RestController和Controller
@ResponseBody,返回json数据

5.员工信息分页查询

like的第一个条件是if的判断
page查询不需返回,会自动放入pageInfo对象并返回
传给前端的是数字,前端做的解析并展示

  1. 启用/禁用员工账号

消息转换器

  1. 编辑员工信息

分类管理

  1. 公共字段自动填充

功能完善:使用ThreadLocal获取当前用户id
一次请求,涉及的所有方法,属于同一个线程

  1. 新增分类

  2. 分类信息分页查询

  3. 删除分类

dish 菜品
setmeal 套餐

自定义业务异常

全局异常处理器捕获自定义异常

5.修改分类
菜品管理

1.文件上传下载

file首先存储在一个临时文件中,请求完成后会自动删除

参数名必须是file,和前端的name=file保持一致

手动改为jpg,其实是同一个文件

配置文件

使用原始文件名

使用uuid生成随机文件名
加上原始文件的后缀,lastIndexOf()包括了“点”

配置文件,必须存在配置的目录,所以代码需要首先判断是否存在,不存在则创建
File既是文件,又是目录

目录:配置地址,判断是否存在
+
文件:uuid文件名+截取原始后缀

最后,需要给页面传送文件名

文件下载
通过流传给浏览器,所以方法无需返回值,是void

两个流,一个input流,读完的数据放入数组中,然后再将数据放入output流。最后刷新,关闭两个流。
实际上是:input流,读一节数组的长度,放入数组中,流到output流中;再读一节…

  1. 新增菜品

菜品表

口味表

菜品的下拉列表,选择菜品分类

新增菜品

  1. 菜品信息分页查询

发送了多个请求
此时,菜品分类前端展示有问题,只是id

原始代码:

页面需要dto

拷贝属性,第一个属性:源,第二个属性:目标,第三个属性:不拷贝哪些
records 单独赋值

  1. 修改菜品
    回显数据

  2. 套餐管理

  3. 新增套餐

  4. 套餐信息分页查询
    在开发代码之前,需要梳理一下套餐分页查询时前端页面和服务端的交互过程:
    1、页面(backend/page/combo/list.html)发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端,获取分页数据
    2、页面发送请求,请求服务端进行图片下载,用于页面图片展示
    开发套餐信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。

请求URL: http://127.0.0.1:8080/setmeal/page

请求方式:GET

参数:page,pageSize,name

controller.SetmealController

@Autowired
private CategoryService categoryService;
@GetMapping(“/page”)
public R page(int page,int pageSize,String name){
//分页构造器对象
Page pageInfo = new Page<>(page,pageSize);
Page dtoPage = new Page<>(page,pageSize);

LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
//添加查询条件,根据name进行like模糊查询
queryWrapper.like(name!= null ,Setmeal::getName,name);
//添加排序条件,根据跟新时间降序排列
queryWrapper.orderByDesc(Setmeal::getUpdateTime);

setmealService.page(pageInfo,queryWrapper);
//拷贝对象
BeanUtils.copyProperties(pageInfo,dtoPage,"records");
List<Setmeal> records = pageInfo.getRecords();

List<SetmealDto> list=records.stream().map((item)->{
    SetmealDto setmealDto = new SetmealDto();
    //对象拷贝
    BeanUtils.copyProperties(item,setmealDto);
    //分类id
    Long categoryId = item.getCategoryId();
    //根据分类id查询分类对象
    Category category = categoryService.getById(categoryId);
    if(category != null){
        String categoryName = category.getName();
        setmealDto.setCategoryName(categoryName);
    }
    return setmealDto;
}).collect(Collectors.toList());

dtoPage.setRecords(list);

return R.success(dtoPage);

}

  1. 删除套餐
    套餐菜品关系表的原因:因为一个菜品可能不属于任何一个套餐啊!所以没有在菜品表中增加一个字段,而是新增了一整张表。

在套餐管理列表页面点击删除按钮,可以删除对应的套餐信息。也可以通过复选框选择多个套餐,点击批量删除按钮一次删除多个套餐。注意,对于状态为售卖中的套餐不能删除,需要先停售,然后才能删除。

请求URL:http://127.0.0.1:8080/setmeal

⚝ 请求方式:DELETE

⚝ 参数:ids

参数说明:ids:被删除的id之间用“,”间隔

如:ids:1415580119015145474,1556280893128380418

service.SetmealService

/**

  • 删除套餐,同时需要删除套餐和菜品的关联数据
  • **/

public void removeWithDish(List ids);
SetmealServiceImpl

/**

  • 删除套餐,同时需要删除套餐和菜品的关联数据

  • **/
    @Override
    @Transactional
    public void removeWithDish(List ids) {

    //查询套餐状态,确定是否可用删除(套餐的 status=1,表示套餐正在售卖,不能删除,如果非要删除需要停售套餐)
    //select count(*) from setmeal where id in (1,2,3) and status=1;
    LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.in(Setmeal::getId,ids);
    queryWrapper.eq(Setmeal::getStatus,1);

    int count = this.count(queryWrapper);
    if(count >0){
    //如果不能删除,抛出一个业务异常
    throw new CustomException(“套餐正在售卖中,删除失败”);
    }
    //如果可以删除,先删除套餐表中的数据–setmeal
    this.removeByIds(ids);

    //删除关系表中的数据–setmeal_dish
    //delete from setmeal_dish where setmeal_id in (1,2,3)
    LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.in(SetmealDish::getSetmealId,ids);
    //删除关系表中的数据----setmeal_dish
    setmealDishService.remove(lambdaQueryWrapper);
    }

controller.SetmealController

//删除与批量删除套餐
@DeleteMapping
public R delete(@RequestParam List ids){
log.info(“ids: {}”,ids);
setmealService.removeWithDish(ids);

return R.success("套餐数据删除成功");

}
我们进入数据库手动将字段status=0使其停售。以便测试删除功能。
————————————————
版权声明:本文为CSDN博主「快乐的小龚」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_67445519/article/details/127167138

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值