基于SpringBoot+MyBatisPlus的外卖项目
- 1、软件开发整体介绍
- 软件开发流程
- 角色分工
- 2、外卖项目介绍
- 项目介绍
- 产品展示
- 后台系统管理
- 移动端
- 技术选型
- 功能结构
- 角色
- 3、开发环境的搭建
- 开发环境说明
- 建库
- 建表
- Maven项目搭建
- 项目的目录结构
- pom.xml
- application.yml
- ReggieApplication启动类
- 配置静态资源映射
- 4、登录功能
- 4.1、后台登录功能
- 需求分析
- 代码编写
- R.java
- 实体类
- EmployeeMapper
- EmployeeService
- EmployeeServiceImpl
- EmployeeController
- 页面展示
- 4.2、后台登出功能
- 需求分析
- 代码编写
- 页面展示
- 4.3、完善登录功能
- 问题分析
- 代码编写
- LoginCheckFilter
- 5、员工管理
- 5.1、新增员工
- 需求分析
- 数据模型
- 代码开发
- 代码编写
- 异常捕获
- 小结
- 5.2、员工信息分页查询
- 需求分析
- 代码开发
- MyBatisPlusConfig配置分页插件
- 5.3、启用/禁用员工账号
- 需求分析
- 代码编写
- 编写一个通用的update方法
- 功能测试
- 功能修复
- 5.3、编辑员工
- 需求分析
- 代码编写
- 5.4、公共字段自动填充
- 问题分析
- 代码实现
- 功能完善
- ThreadLocal
- 6、分类管理
- 6.1、新增菜品分类
- 需求分析
- 数据模型
- 代码开发
- 6.1、新增菜品的分页查询
- 需求分析
- 代码开发
- 6.2、删除分类
- 需求分析
- 代码开发
- 功能完善
- GlobalExceptionHandler
- **CustomException**
- CategoryServiceImpl
- 6.3、修改分类
- 需求分析
- 代码编写
- 7、菜品管理
- 7.1、文件上传下载
- 文件上传介绍
- 文件下载介绍
- 文件上传代码实现
- 文件下载代码实现
- 7.2、新增菜品
- 需求分析
- 数据模型
- 代码开发
- DishServiceImpl
- DishController
- 7.3、菜品信息分页查询
- 需求分析
- 代码开发
- 难点
- 7.4、修改菜品
- 需求分析
- 代码开发
- controller
- DishServiceImpl
- 7.5、修改菜品的停/起售状态
- DishController
- DishServiceImpl
- 7.6、删除菜品
- 8、套餐管理
- 8.1、新增套餐
- 需求分析
- 数据模型
- 代码开发
- DishController
- SetmealDishController
- SetmealServiceImpl
- 8.2、套餐信息分页查询
- 需求分析
- 代码开发
- 8.3、删除套餐
- 需求分析
- 代码开发
- SetmealController
- SetmealServiceImpl
- 8.4、修改套餐
- SetmealController
- SetmealService
- SetmealServiceImpl
- 8.5、停售、启售套餐
- SetmealController
- SetmealServiceImpl
- 9、前端–手机验证码登录
- 9.1、短信发送
- 阿里云短信服务
- 设置签名
- 添加模板详情
- 设置AccessKey
- 添加权限
- 购买短信免费试用包
- 代码开发
- pom
- 导入utils工具类
- 9.2、手机验证码登录
- 需求分析
- 数据模型
- 代码开发
- 移动端页面放行的请求
- UserController
- 10、前端–导入用户地址簿
- 需求分析
- 数据模型
- 代码开发
- AddressBookController
- 11、前端–菜品展示
- 需求分析
- 代码开发
- 展示flavor口味信息
- 套餐信息展示
- 12、前端–购物车
- 需求分析
- 数据模型
- 代码开发
- 13、前端–用户下单
- 需求分析
- 数据模型
- 代码开发
- OrderController
- OrderService
- OrderServiceImpl
- 14、代码托管
- Git版本管理
- Gitee
- Github
- 项目所需资料
申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计86935字,阅读大概需要3分钟
更多学习内容, 欢迎关注我的个人公众号:不懂开发的程序猿
写在前面的几句话:
【警告】本篇博客较长,若引起阅读不适,建议收藏,稍后再读
【说明】该外卖项目是基于SpringBoot + MyBatisPlus为框架来开发的,前端页面框架都是现成的,只需要Java后端开发程序员编写对应的接口功能和服务,是一个很不错的练手项目。项目也非常适合作为大学生的课设,毕设
【文档】本篇博客详细介绍了该外卖项目的开发步骤,如果需要写课程设计或本科毕业论文文档,建议参考我下面这篇博客,内有详细的文档说明
点餐平台文档说明
1、软件开发整体介绍
软件开发流程
角色分工
2、外卖项目介绍
项目介绍
分为后台系统管理和移动端两部分
后台系统管理供商家:对菜品、套餐、订单等进行管理维护等
移动端供消费者:在线浏览,添加购物车,下单 等
3步开发思路:
第一:主要实现基本需求,其中移动端应用通过H5实现,用户可以通过手机浏览器访问。
第二:主要针对移动端应用进行改进,使用微信小程序实现,用户使用起来更加方便。
第三:主要针对系统进行优化升级,提高系统的访问性能。
产品展示
后台系统管理
登录页
员工管理页
分类管理
菜品管理
套餐管理
订单明细
移动端
登录页
首页
下单确认页
下单成功页
个人中心页
地址管理页
历史订单页
技术选型
功能结构
角色
3、开发环境的搭建
开发环境说明
工具 | 版本 |
---|---|
后台 | SpringBoot + MyBatisPlus |
服务器 | Tomcat 8.5.73 |
数据库 | MySQL 8.0.28 |
Build Tools | Maven 3.8.5 |
前端 | Vue + ElementUI |
开发工具 | IDEA 2022.3 |
版本管理工具 | Git |
建库
建表
/*SQLyog Ultimate v12.08 (64 bit)MySQL - 8.0.27 : Database - reggie**********************************************************************//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;CREATE DATABASE /*!32312 IF NOT EXISTS*/`reggie` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;USE `reggie`;/*Table structure for table `address_book` */DROP TABLE IF EXISTS `address_book`;CREATE TABLE `address_book` ( `id` bigint NOT NULL COMMENT '主键', `user_id` bigint NOT NULL COMMENT '用户id', `consignee` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '收货人', `sex` tinyint NOT NULL COMMENT '性别 0 女 1 男', `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '手机号', `province_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '省级区划编号', `province_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '省级名称', `city_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '市级区划编号', `city_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '市级名称', `district_code` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '区级区划编号', `district_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '区级名称', `detail` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '详细地址', `label` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '标签', `is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '默认 0 否 1是', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `create_user` bigint NOT NULL COMMENT '创建人', `update_user` bigint NOT NULL COMMENT '修改人', `is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='地址管理';/*Data for the table `address_book` */insert into `address_book`(`id`,`user_id`,`consignee`,`sex`,`phone`,`province_code`,`province_name`,`city_code`,`city_name`,`district_code`,`district_name`,`detail`,`label`,`is_default`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1417414526093082626,1417012167126876162,'小明',1,'13812345678',NULL,NULL,NULL,NULL,NULL,NULL,'昌平区金燕龙办公楼','公司',1,'2021-07-20 17:22:12','2021-07-20 17:26:33',1417012167126876162,1417012167126876162,0),(1417414926166769666,1417012167126876162,'小李',1,'13512345678',NULL,NULL,NULL,NULL,NULL,NULL,'测试','家',0,'2021-07-20 17:23:47','2021-07-20 17:23:47',1417012167126876162,1417012167126876162,0),(1628270733663694849,1627997218788163586,'金阳',1,'17671789248',NULL,NULL,NULL,NULL,NULL,NULL,'湖北工业大学','学校',1,'2023-02-22 13:49:29','2023-02-22 13:49:32',1627997218788163586,1627997218788163586,0);/*Table structure for table `category` */DROP TABLE IF EXISTS `category`;CREATE TABLE `category` ( `id` bigint NOT NULL COMMENT '主键', `type` int DEFAULT NULL COMMENT '类型 1 菜品分类 2 套餐分类', `name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '分类名称', `sort` int NOT NULL DEFAULT '0' COMMENT '顺序', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `create_user` bigint NOT NULL COMMENT '创建人', `update_user` bigint NOT NULL COMMENT '修改人', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `idx_category_name` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='菜品及套餐分类';/*Data for the table `category` */insert into `category`(`id`,`type`,`name`,`sort`,`create_time`,`update_time`,`create_user`,`update_user`) values (1397844263642378242,1,'湘菜',1,'2021-05-27 09:16:58','2023-02-19 16:51:09',1,1),(1397844303408574465,1,'川菜',2,'2021-05-27 09:17:07','2021-06-02 14:27:22',1,1),(1397844391040167938,1,'粤菜',3,'2021-05-27 09:17:28','2021-07-09 14:37:13',1,1),(1413341197421846529,1,'饮品',11,'2021-07-09 11:36:15','2021-07-09 14:39:15',1,1),(1413342269393674242,2,'商务套餐',5,'2021-07-09 11:40:30','2021-07-09 14:43:45',1,1),(1413384954989060097,1,'主食',12,'2021-07-09 14:30:07','2021-07-09 14:39:19',1,1),(1413386191767674881,2,'儿童套餐',6,'2021-07-09 14:35:02','2021-07-09 14:39:05',1,1),(1627130608250593281,1,'湖北菜',4,'2023-02-19 10:19:02','2023-02-19 10:19:02',1,1);/*Table structure for table `dish` */DROP TABLE IF EXISTS `dish`;CREATE TABLE `dish` ( `id` bigint NOT NULL COMMENT '主键', `name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '菜品名称', `category_id` bigint NOT NULL COMMENT '菜品分类id', `price` decimal(10,2) DEFAULT NULL COMMENT '菜品价格', `code` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '商品码', `image` varchar(200) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '图片', `description` varchar(400) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '描述信息', `status` int NOT NULL DEFAULT '1' COMMENT '0 停售 1 起售', `sort` int NOT NULL DEFAULT '0' COMMENT '顺序', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `create_user` bigint NOT NULL COMMENT '创建人', `update_user` bigint NOT NULL COMMENT '修改人', `is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `idx_dish_name` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='菜品管理';/*Data for the table `dish` */insert into `dish`(`id`,`name`,`category_id`,`price`,`code`,`image`,`description`,`status`,`sort`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628019384179052546,'红烧肉',1397844263642378242,'3900.00','','90c9f385-5c18-491a-90f2-a4c8df198376.jpg','红烧肉',1,0,'2023-02-21 21:10:43','2023-02-21 21:10:43',1627997218788163586,1627997218788163586,0),(1628019727558332417,'麻辣鸡丝',1397844303408574465,'3900.00','','b19c64b2-378d-43d9-975f-2367bcc99e70.jpg','麻辣鸡丝',1,0,'2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628020011776954369,'辣子鸡',1627130608250593281,'4900.00','','d79ac164-8e43-4478-9d57-539764d1c5a8.jpg','来自鲜嫩美味的小鸡,值得一尝',1,0,'2023-02-21 21:13:13','2023-02-22 14:42:06',1627997218788163586,1627997218788163586,0),(1628020274659151874,'基围虾',1397844263642378242,'5900.00','','05010fb3-c055-41ff-8da8-4d941daea332.jpg','基围虾',1,0,'2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020414488858625,'麻辣兔头',1397844303408574465,'12800.00','','703fb335-5593-49be-a629-e2522344212d.jpg','麻辣兔头',1,0,'2023-02-21 21:14:49','2023-02-21 21:14:49',1627997218788163586,1627997218788163586,0),(1628020624501854210,'邵阳猪血丸子',1397844391040167938,'5900.00','','79f6db2d-99d9-40f0-adee-a6750036d40e.jpg','邵阳猪血丸子',1,0,'2023-02-21 21:15:39','2023-02-21 21:15:39',1627997218788163586,1627997218788163586,0),(1628020855322791938,'烤乳猪',1397844391040167938,'9900.00','','8197826f-8bcd-44a1-9d0e-e742b0265e7d.jpeg','白切鸡',1,0,'2023-02-21 21:16:34','2023-02-21 21:19:39',1627997218788163586,1627997218788163586,0),(1628020978719215617,'脆皮烧鹅',1627130608250593281,'15800.00','','3d6188da-68f1-4299-89fd-04c7ab744110.jpeg','脆皮烧鹅',1,0,'2023-02-21 21:17:03','2023-02-22 14:41:44',1627997218788163586,1627997218788163586,0),(1628021120151146497,'上汤焗龙虾',1627130608250593281,'15800.00','','d2dbe897-3b8b-4e5c-99d8-b7ca159ba5b9.jpeg','上汤焗龙虾',1,0,'2023-02-21 21:17:37','2023-02-22 14:41:25',1627997218788163586,1627997218788163586,0),(1628021265471197185,'宫保鸡丁',1397844303408574465,'6900.00','','95f8b479-ae76-4107-9b08-3c62ae7f7fd0.jpg','宫保鸡丁',1,0,'2023-02-21 21:18:12','2023-02-22 14:40:23',1627997218788163586,1627997218788163586,0),(1628021771191013377,'白切鸡',1397844391040167938,'7900.00','','b5d537cf-0d6c-42ae-9210-94c981087d52.jpeg','白切鸡',1,0,'2023-02-21 21:20:12','2023-02-21 21:20:12',1627997218788163586,1627997218788163586,0),(1628022122845655041,'青椒炖鸡丁',1627130608250593281,'9900.00','','9b7494ee-1714-40ee-a94e-18c769678671.jpg','青椒炖鸡丁',1,0,'2023-02-21 21:21:36','2023-02-21 21:21:36',1627997218788163586,1627997218788163586,0),(1628022255993835522,'老火靓汤',1627130608250593281,'10900.00','','a72af50a-264c-4cf1-9da0-28e1eb98aa5c.jpeg','老火靓汤',1,0,'2023-02-21 21:22:08','2023-02-21 21:22:08',1627997218788163586,1627997218788163586,0),(1628022421907918850,'清蒸河鲜海鲜',1397844303408574465,'2900.00','','06b6c68f-db38-4bff-a8f4-131830291cec.jpg','清蒸河鲜海鲜',1,0,'2023-02-21 21:22:47','2023-02-21 21:22:47',1627997218788163586,1627997218788163586,0),(1628022523112280066,'王老吉',1413341197421846529,'500.00','','3e7ab2fe-01fa-4eb6-828e-b7998583a4e1.png','王老吉',1,0,'2023-02-21 21:23:11','2023-02-21 21:23:11',1627997218788163586,1627997218788163586,0),(1628022754352648193,'麻辣水煮鱼',1397844391040167938,'6500.00','','5f614bfa-f62c-4d5d-a4e3-852d6ce53d62.jpeg','麻辣水煮鱼',1,0,'2023-02-21 21:24:07','2023-02-22 14:40:56',1627997218788163586,1627997218788163586,0),(1628022918689673218,'清炒素食',1627130608250593281,'1900.00','','d8783e07-a8da-4e4e-8826-0c0e6990a08f.jpg','清炒素食',1,0,'2023-02-21 21:24:46','2023-02-21 21:24:46',1627997218788163586,1627997218788163586,0),(1628023021122965506,'啤酒',1413341197421846529,'1000.00','','bbfe22ba-9bd5-486a-ae83-22e108dddc47.png','啤酒',1,0,'2023-02-21 21:25:10','2023-02-21 21:25:10',1627997218788163586,1627997218788163586,0),(1628023133450620930,'麻辣鱼片',1397844303408574465,'3900.00','','ffdbeb37-0fbe-4190-a52a-3a16478f366e.jpg','麻辣鱼片',1,0,'2023-02-21 21:25:37','2023-02-21 21:25:37',1627997218788163586,1627997218788163586,0),(1628023363927625729,'烤乳鸽',1397844391040167938,'7900.00','','a1848e46-eb33-4957-bd77-039caaee79c2.jpeg','烤乳鸽',1,0,'2023-02-21 21:26:32','2023-02-21 21:26:32',1627997218788163586,1627997218788163586,0),(1628023490318782465,'大米饭',1413384954989060097,'500.00','','d19db29f-c016-410d-ac01-a3742ea1ea3c.png','大米饭',1,0,'2023-02-21 21:27:02','2023-02-21 21:27:02',1627997218788163586,1627997218788163586,0),(1628023694518472706,'辣子鸡丁',1397844263642378242,'3900.00','','c67657d7-4cbf-4d0c-b20c-7ab66ad52514.jpg','辣子鸡丁',1,0,'2023-02-21 21:27:51','2023-02-21 21:27:51',1627997218788163586,1627997218788163586,0),(1628023841423970305,'口味蛇',1627130608250593281,'8800.00','','3d486c18-6dd8-4464-a087-bd93cfc987bf.jpg','口味蛇',1,0,'2023-02-21 21:28:26','2023-02-21 21:28:26',1627997218788163586,1627997218788163586,0);/*Table structure for table `dish_flavor` */DROP TABLE IF EXISTS `dish_flavor`;CREATE TABLE `dish_flavor` ( `id` bigint NOT NULL COMMENT '主键', `dish_id` bigint NOT NULL COMMENT '菜品', `name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '口味名称', `value` varchar(500) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '口味数据list', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `create_user` bigint NOT NULL COMMENT '创建人', `update_user` bigint NOT NULL COMMENT '修改人', `is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='菜品口味关系表';/*Data for the table `dish_flavor` */insert into `dish_flavor`(`id`,`dish_id`,`name`,`value`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628019384321658881,1628019384179052546,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:10:43','2023-02-21 21:10:43',1627997218788163586,1627997218788163586,0),(1628019384321658882,1628019384179052546,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:10:43','2023-02-21 21:10:43',1627997218788163586,1627997218788163586,0),(1628019727621246978,1628019727558332417,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628019727621246979,1628019727558332417,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628019727621246980,1628019727558332417,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:12:05','2023-02-21 21:12:05',1627997218788163586,1627997218788163586,0),(1628020274726260738,1628020274659151874,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020274726260739,1628020274659151874,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020274726260740,1628020274659151874,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:14:15','2023-02-21 21:14:15',1627997218788163586,1627997218788163586,0),(1628020414488858626,1628020414488858625,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:14:49','2023-02-21 21:14:49',1627997218788163586,1627997218788163586,0),(1628020414488858627,1628020414488858625,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:14:49','2023-02-21 21:14:49',1627997218788163586,1627997218788163586,0),(1628020624573157378,1628020624501854210,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:15:39','2023-02-21 21:15:39',1627997218788163586,1627997218788163586,0),(1628020624573157379,1628020624501854210,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:15:39','2023-02-21 21:15:39',1627997218788163586,1627997218788163586,0),(1628020855389900802,1628020855322791938,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:19:39','2023-02-21 21:19:39',1627997218788163586,1627997218788163586,0),(1628020855389900803,1628020855322791938,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:19:39','2023-02-21 21:19:39',1627997218788163586,1627997218788163586,0),(1628021771191013378,1628021771191013377,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:20:12','2023-02-21 21:20:12',1627997218788163586,1627997218788163586,0),(1628021771191013379,1628021771191013377,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:20:12','2023-02-21 21:20:12',1627997218788163586,1627997218788163586,0),(1628022122971484162,1628022122845655041,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:21:36','2023-02-21 21:21:36',1627997218788163586,1627997218788163586,0),(1628022122971484163,1628022122845655041,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:21:36','2023-02-21 21:21:36',1627997218788163586,1627997218788163586,0),(1628022256186773505,1628022255993835522,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:22:08','2023-02-21 21:22:08',1627997218788163586,1627997218788163586,0),(1628022256186773506,1628022255993835522,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:22:08','2023-02-21 21:22:08',1627997218788163586,1627997218788163586,0),(1628022421975027713,1628022421907918850,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:22:47','2023-02-21 21:22:47',1627997218788163586,1627997218788163586,0),(1628022421975027714,1628022421907918850,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:22:47','2023-02-21 21:22:47',1627997218788163586,1627997218788163586,0),(1628022523175194626,1628022523112280066,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:23:11','2023-02-21 21:23:11',1627997218788163586,1627997218788163586,0),(1628022918823890945,1628022918689673218,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:24:46','2023-02-21 21:24:46',1627997218788163586,1627997218788163586,0),(1628022918823890946,1628022918689673218,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:24:46','2023-02-21 21:24:46',1627997218788163586,1627997218788163586,0),(1628023021190074370,1628023021122965506,'温度','[\"热饮\",\"常温\",\"去冰\",\"少冰\",\"多冰\"]','2023-02-21 21:25:10','2023-02-21 21:25:10',1627997218788163586,1627997218788163586,0),(1628023133576450049,1628023133450620930,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:25:37','2023-02-21 21:25:37',1627997218788163586,1627997218788163586,0),(1628023133576450050,1628023133450620930,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:25:37','2023-02-21 21:25:37',1627997218788163586,1627997218788163586,0),(1628023364061843457,1628023363927625729,'甜味','[\"无糖\",\"少糖\",\"半糖\",\"多糖\",\"全糖\"]','2023-02-21 21:26:32','2023-02-21 21:26:32',1627997218788163586,1627997218788163586,0),(1628023364061843458,1628023363927625729,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:26:32','2023-02-21 21:26:32',1627997218788163586,1627997218788163586,0),(1628023490448805890,1628023490318782465,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:27:02','2023-02-21 21:27:02',1627997218788163586,1627997218788163586,0),(1628023694585581569,1628023694518472706,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:27:51','2023-02-21 21:27:51',1627997218788163586,1627997218788163586,0),(1628023694585581570,1628023694518472706,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:27:51','2023-02-21 21:27:51',1627997218788163586,1627997218788163586,0),(1628023841553993729,1628023841423970305,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-21 21:28:26','2023-02-21 21:28:26',1627997218788163586,1627997218788163586,0),(1628023841553993730,1628023841423970305,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-21 21:28:26','2023-02-21 21:28:26',1627997218788163586,1627997218788163586,0),(1628283539888816129,1628021265471197185,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:40:23','2023-02-22 14:40:23',1627997218788163586,1627997218788163586,0),(1628283539888816130,1628021265471197185,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:40:23','2023-02-22 14:40:23',1627997218788163586,1627997218788163586,0),(1628283681786314754,1628022754352648193,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:40:56','2023-02-22 14:40:56',1627997218788163586,1627997218788163586,0),(1628283681786314755,1628022754352648193,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:40:56','2023-02-22 14:40:56',1627997218788163586,1627997218788163586,0),(1628283800552226817,1628021120151146497,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:41:25','2023-02-22 14:41:25',1627997218788163586,1627997218788163586,0),(1628283800552226818,1628021120151146497,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:41:25','2023-02-22 14:41:25',1627997218788163586,1627997218788163586,0),(1628283883154849793,1628020978719215617,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:41:44','2023-02-22 14:41:44',1627997218788163586,1627997218788163586,0),(1628283883154849794,1628020978719215617,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:41:44','2023-02-22 14:41:44',1627997218788163586,1627997218788163586,0),(1628283974536151041,1628020011776954369,'忌口','[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]','2023-02-22 14:42:06','2023-02-22 14:42:06',1627997218788163586,1627997218788163586,0),(1628283974536151042,1628020011776954369,'辣度','[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]','2023-02-22 14:42:06','2023-02-22 14:42:06',1627997218788163586,1627997218788163586,0);/*Table structure for table `employee` */DROP TABLE IF EXISTS `employee`;CREATE TABLE `employee` ( `id` bigint NOT NULL COMMENT '主键', `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '姓名', `username` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户名', `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '密码', `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '手机号', `sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '性别', `id_number` varchar(18) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '身份证号', `status` int NOT NULL DEFAULT '1' COMMENT '状态 0:禁用,1:正常', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `create_user` bigint NOT NULL COMMENT '创建人', `update_user` bigint NOT NULL COMMENT '修改人', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `idx_username` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='员工信息';/*Data for the table `employee` */insert into `employee`(`id`,`name`,`username`,`password`,`phone`,`sex`,`id_number`,`status`,`create_time`,`update_time`,`create_user`,`update_user`) values (1,'管理员','admin','e10adc3949ba59abbe56e057f20f883e','13812312312','1','110101199001010047',1,'2021-05-06 17:20:07','2021-05-10 02:24:09',1,1),(1626857776597762049,'张三1','zhangsan','e10adc3949ba59abbe56e057f20f883e','17671789248','1','421181199805171311',1,'2023-02-18 16:14:54','2023-02-18 22:06:50',1,1),(1626945547559514113,'小李','test001','e10adc3949ba59abbe56e057f20f883e','17612345678','1','421181123456781234',1,'2023-02-18 22:04:04','2023-02-19 08:52:25',1,1);/*Table structure for table `order_detail` */DROP TABLE IF EXISTS `order_detail`;CREATE TABLE `order_detail` ( `id` bigint NOT NULL COMMENT '主键', `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '名字', `image` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '图片', `order_id` bigint NOT NULL COMMENT '订单id', `dish_id` bigint DEFAULT NULL COMMENT '菜品id', `setmeal_id` bigint DEFAULT NULL COMMENT '套餐id', `dish_flavor` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '口味', `number` int NOT NULL DEFAULT '1' COMMENT '数量', `amount` decimal(10,2) NOT NULL COMMENT '金额', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='订单明细表';/*Data for the table `order_detail` */insert into `order_detail`(`id`,`name`,`image`,`order_id`,`dish_id`,`setmeal_id`,`dish_flavor`,`number`,`amount`) values (1628281691748474882,'儿童套餐A','17fb2dcf-c06a-46c4-8ba6-8cb461d84031.jpg',1628281691555536898,NULL,1628024994765295618,NULL,1,'59.00'),(1628281691748474883,'辣子鸡丁','c67657d7-4cbf-4d0c-b20c-7ab66ad52514.jpg',1628281691555536898,1628023694518472706,NULL,'不要香菜,中辣',1,'39.00'),(1628281691748474884,'麻辣鱼片','ffdbeb37-0fbe-4190-a52a-3a16478f366e.jpg',1628281691555536898,1628023133450620930,NULL,'不要蒜,中辣',1,'39.00'),(1628281691748474885,'宫保鸡丁','95f8b479-ae76-4107-9b08-3c62ae7f7fd0.jpg',1628281691555536898,1628021265471197185,NULL,NULL,1,'69.00'),(1628281691748474886,'麻辣兔头','703fb335-5593-49be-a629-e2522344212d.jpg',1628281691555536898,1628020414488858625,NULL,'去冰,中辣',1,'128.00'),(1628281691811389441,'商务套餐A','fb706fe0-b57f-46da-9f70-f209cc489f39.jpg',1628281691555536898,NULL,1628024830898032642,NULL,1,'99.00'),(1628302223755788290,'辣子鸡丁','c67657d7-4cbf-4d0c-b20c-7ab66ad52514.jpg',1628302223562850306,1628023694518472706,NULL,'不要蒜,微辣',1,'39.00'),(1628302223755788291,'商务套餐A','fb706fe0-b57f-46da-9f70-f209cc489f39.jpg',1628302223562850306,NULL,1628024830898032642,NULL,1,'99.00'),(1628302223755788292,'儿童套餐A','17fb2dcf-c06a-46c4-8ba6-8cb461d84031.jpg',1628302223562850306,NULL,1628024994765295618,NULL,1,'59.00');/*Table structure for table `orders` */DROP TABLE IF EXISTS `orders`;CREATE TABLE `orders` ( `id` bigint NOT NULL COMMENT '主键', `number` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '订单号', `status` int NOT NULL DEFAULT '1' COMMENT '订单状态 1待付款,2待派送,3已派送,4已完成,5已取消', `user_id` bigint NOT NULL COMMENT '下单用户', `address_book_id` bigint NOT NULL COMMENT '地址id', `order_time` datetime NOT NULL COMMENT '下单时间', `checkout_time` datetime NOT NULL COMMENT '结账时间', `pay_method` int NOT NULL DEFAULT '1' COMMENT '支付方式 1微信,2支付宝', `amount` decimal(10,2) NOT NULL COMMENT '实收金额', `remark` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '备注', `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `consignee` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='订单表';/*Data for the table `orders` */insert into `orders`(`id`,`number`,`status`,`user_id`,`address_book_id`,`order_time`,`checkout_time`,`pay_method`,`amount`,`remark`,`phone`,`address`,`user_name`,`consignee`) values (1628281691555536898,'1628281691555536898',2,1627997218788163586,1628270733663694849,'2023-02-22 14:33:02','2023-02-22 14:33:02',1,'433.00','','17671789248','湖北工业大学',NULL,'金阳'),(1628302223562850306,'1628302223562850306',2,1627997218788163586,1628270733663694849,'2023-02-22 15:54:37','2023-02-22 15:54:37',1,'197.00','','17671789248','湖北工业大学',NULL,'金阳');/*Table structure for table `setmeal` */DROP TABLE IF EXISTS `setmeal`;CREATE TABLE `setmeal` ( `id` bigint NOT NULL COMMENT '主键', `category_id` bigint NOT NULL COMMENT '菜品分类id', `name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '套餐名称', `price` decimal(10,2) NOT NULL COMMENT '套餐价格', `status` int DEFAULT NULL COMMENT '状态 0:停用 1:启用', `code` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '编码', `description` varchar(512) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '描述信息', `image` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '图片', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `create_user` bigint NOT NULL COMMENT '创建人', `update_user` bigint NOT NULL COMMENT '修改人', `is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `idx_setmeal_name` (`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='套餐';/*Data for the table `setmeal` */insert into `setmeal`(`id`,`category_id`,`name`,`price`,`status`,`code`,`description`,`image`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628024830898032642,1413342269393674242,'商务套餐A','9900.00',1,'','商务套餐A','fb706fe0-b57f-46da-9f70-f209cc489f39.jpg','2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024994765295618,1413386191767674881,'儿童套餐A','5900.00',1,'','儿童套餐A','17fb2dcf-c06a-46c4-8ba6-8cb461d84031.jpg','2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0);/*Table structure for table `setmeal_dish` */DROP TABLE IF EXISTS `setmeal_dish`;CREATE TABLE `setmeal_dish` ( `id` bigint NOT NULL COMMENT '主键', `setmeal_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '套餐id ', `dish_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '菜品id', `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '菜品名称 (冗余字段)', `price` decimal(10,2) DEFAULT NULL COMMENT '菜品原价(冗余字段)', `copies` int NOT NULL COMMENT '份数', `sort` int NOT NULL DEFAULT '0' COMMENT '排序', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', `create_user` bigint NOT NULL COMMENT '创建人', `update_user` bigint NOT NULL COMMENT '修改人', `is_deleted` int NOT NULL DEFAULT '0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='套餐菜品关系';/*Data for the table `setmeal_dish` */insert into `setmeal_dish`(`id`,`setmeal_id`,`dish_id`,`name`,`price`,`copies`,`sort`,`create_time`,`update_time`,`create_user`,`update_user`,`is_deleted`) values (1628024830960947201,'1628024830898032642','1628023694518472706','辣子鸡丁','3900.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024830960947202,'1628024830898032642','1628023490318782465','大米饭','500.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024830960947203,'1628024830898032642','1628023021122965506','啤酒','1000.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024830960947204,'1628024830898032642','1628023363927625729','烤乳鸽','7900.00',1,0,'2023-02-21 21:32:22','2023-02-21 21:32:22',1627997218788163586,1627997218788163586,0),(1628024994832404481,'1628024994765295618','1628023490318782465','大米饭','500.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0),(1628024994832404482,'1628024994765295618','1628022523112280066','王老吉','500.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0),(1628024994832404483,'1628024994765295618','1628022918689673218','清炒素食','1900.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0),(1628024994832404484,'1628024994765295618','1628023363927625729','烤乳鸽','7900.00',1,0,'2023-02-21 21:33:01','2023-02-21 21:33:01',1627997218788163586,1627997218788163586,0);/*Table structure for table `shopping_cart` */DROP TABLE IF EXISTS `shopping_cart`;CREATE TABLE `shopping_cart` ( `id` bigint NOT NULL COMMENT '主键', `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '名称', `image` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '图片', `user_id` bigint NOT NULL COMMENT '主键', `dish_id` bigint DEFAULT NULL COMMENT '菜品id', `setmeal_id` bigint DEFAULT NULL COMMENT '套餐id', `dish_flavor` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '口味', `number` int NOT NULL DEFAULT '1' COMMENT '数量', `amount` decimal(10,2) NOT NULL COMMENT '金额', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='购物车';/*Data for the table `shopping_cart` *//*Table structure for table `user` */DROP TABLE IF EXISTS `user`;CREATE TABLE `user` ( `id` bigint NOT NULL COMMENT '主键', `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '姓名', `phone` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '手机号', `sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '性别', `id_number` varchar(18) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '身份证号', `avatar` varchar(500) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '头像', `status` int DEFAULT '0' COMMENT '状态 0:禁用,1:正常', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin COMMENT='用户信息';/*Data for the table `user` */insert into `user`(`id`,`name`,`phone`,`sex`,`id_number`,`avatar`,`status`) values (1627997218788163586,NULL,'17612349248',NULL,NULL,NULL,1);/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
数据表
Maven项目搭建
项目的目录结构
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.5</version> <relativePath/> </parent> <groupId>com.jerry</groupId> <artifactId>reggie</artifactId> <version>1.0</version> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.23</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.5</version> </plugin> </plugins> </build></project>
application.yml
server: port: 8080spring: application: # 应用名称,可选项 name: reggie datasource: druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/reggie" /> 4、登录功能
4.1、后台登录功能
需求分析
代码编写
vo类:将服务器和前端页面传递的数据封装好
R类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回给前端页面
R.java
package com.jerry.reggie.common;import lombok.Data;import java.util.HashMap;import java.util.Map;/** * 通用返回结果,服务器端响应的数据最终都会封装成此对象 * @param */@Datapublic class R<T> { private Integer code; //编码:1成功,0和其它数字为失败 private String msg; //错误信息 private T data; //数据 private Map map = new HashMap(); //动态数据 public static <T> R<T> success(T object) { R<T> r = new R<T>(); r.data = object; r.code = 1; return r; } public static <T> R<T> error(String msg) { R r = new R(); r.msg = msg; r.code = 0; return r; } public R<T> add(String key, Object value) { this.map.put(key, value); return this; }}
实体类
package com.jerry.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;import com.baomidou.mybatisplus.annotation.TableField;import lombok.Data;import java.io.Serializable;import java.time.LocalDateTime;/** * 员工实体类 */@Datapublic class Employee implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String username; private String name; private String password; private String phone; private String sex; private String idNumber;//身份证号 private Integer status; private LocalDateTime createTime; private LocalDateTime updateTime; @TableField(fill = FieldFill.INSERT) private Long createUser; @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateUser;}
EmployeeMapper
package com.jerry.reggie.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.jerry.reggie.entity.Employee;import org.apache.ibatis.annotations.Mapper;/** * ClassName: EmployeeMApper * Package: com.jerry.reggie.mapper * Description: * * @Author jerry_jy * @Create 2023-02-16 14:45 * @Version 1.0 */@Mapperpublic interface EmployeeMapper extends BaseMapper<Employee> {}
EmployeeService
package com.jerry.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;import com.jerry.reggie.entity.Employee;/** * ClassName: EmployeeService * Package: com.jerry.reggie.service * Description: * * @Author jerry_jy * @Create 2023-02-16 14:46 * @Version 1.0 */public interface EmployeeService extends IService<Employee> {}
EmployeeServiceImpl
package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.jerry.reggie.entity.Employee;import com.jerry.reggie.mapper.EmployeeMapper;import com.jerry.reggie.service.EmployeeService;import org.springframework.stereotype.Service;/** * ClassName: EmployeeServiceImpl * Package: com.jerry.reggie.service.impl * Description: * * @Author jerry_jy * @Create 2023-02-16 14:46 * @Version 1.0 */@Servicepublic class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {}
EmployeeController
package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.jerry.reggie.common.R;import com.jerry.reggie.entity.Employee;import com.jerry.reggie.service.EmployeeService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpRequest;import org.springframework.stereotype.Controller;import org.springframework.util.DigestUtils;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;/** * ClassName: EmployeeController * Package: com.jerry.reggie.controller * Description: * * @Author jerry_jy * @Create 2023-02-16 14:52 * @Version 1.0 */@Slf4j@RestController@RequestMapping("/employee")public class EmployeeController { @Autowired private EmployeeService employeeService; @PostMapping("/login") public R<Employee> login(@RequestBody Employee employee, HttpServletRequest request) { //@RequestBody用来接收前端传递给后端的`json`字符串中的数据的(请求体中的数据的),所以前端只能发送POST请求 //1、将页面提交的密码password进行md5加密处理 String pwd = employee.getPassword(); pwd = DigestUtils.md5DigestAsHex(pwd.getBytes()); // 2、根据页面提交的用户名username查询数据库] /** * 我自己写的是 * QueryWrapper queryWrapper = new QueryWrapper(); * employeeService.getOne(queryWrapper.select(employee.getName())); * 查询出来的是null值 */ LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>(); //方法引用的语法格式(语法糖) wrapper.eq(Employee::getUsername,employee.getUsername()); Employee emp = employeeService.getOne(wrapper); // 3、如果没有查询到则返回登录失败结果 if (emp == null) { return R.error("登录失败"); } //4、密码比对,如果不一致则返回登录失败结果 if (!pwd.equals(emp.getPassword())) { return R.error("登录失败"); } //5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果 if (emp.getStatus()!=1){ return R.error("员工账号已禁用"); } // 6、登录成功,将员工id存入Session并返回登录成功结果 Long empId = emp.getId(); request.getSession().setAttribute("empId",empId); return R.success(emp); }}
页面展示
http://localhost:8080/backend/page/login/login.html
http://localhost:8080/backend/index.html
4.2、后台登出功能
需求分析
代码编写
/** * 员工后台登出功能 * @param request * @return */@PostMapping("/logout")public R<String> logout(HttpServletRequest request) { //1、清理Session中的用户id request.getSession().removeAttribute("empId"); // 2、返回结果 return R.success("登出成功");}
页面展示
4.3、完善登录功能
问题分析
代码编写
LoginCheckFilter
package com.jerry.reggie.filter;import com.alibaba.fastjson.JSON;import com.jerry.reggie.common.R;import lombok.extern.slf4j.Slf4j;import org.springframework.util.AntPathMatcher;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * ClassName: LoginCheckFilter * Package: com.jerry.reggie.filter * Description: * * @Author jerry_jy * @Create 2023-02-16 21:50 * @Version 1.0 */@Slf4j@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")public class LoginCheckFilter implements Filter { //路径匹配,支持通配符 public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher(); @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; //1、获取本次请求的URI String uri = request.getRequestURI(); // backend/index.html log.info("拦截到请求:{}", uri); //定义不需要处理的请求路径 String[] urls = new String[]{ "/employee/login", "employee/logout", "/backend/**", "/front/**" }; //2、判断本次请求是否需要处理 boolean check = check(urls, uri); // 3、如果不需要处理,则直接放行 if (check == true) { log.info("本次请求{}不需要处理" + uri); filterChain.doFilter(request, response); return; } //4、判断登录状态,如果已登录,则直接放行 if (request.getSession().getAttribute("empId") != null) { log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("empId")); filterChain.doFilter(request, response); return; } log.info("用户未登录"); // 5、如果未登录则返回未登录结果,通过输出流方式向客户端响应数据 response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN"))); return; } /** * 路径匹配,检查本次请求是否需要放行 * * @param urls * @param uri * @return */ public boolean check(String[] urls, String uri) { for (String url : urls) { boolean match = PATH_MATCHER.match(url, uri); if (match) { return true; } } return false; }}
5、员工管理
5.1、新增员工
需求分析
数据模型
代码开发
代码编写
/** * 新增员工 * @param employee * @return */@PostMappingpublic R<String> save(@RequestBody Employee employee, HttpServletRequest request){ log.info("新增员工,员工信息:{}",employee.toString()); //设置员工的初始密码,需要进行MD5 加密处理 employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes())); employee.setCreateTime(LocalDateTime.now()); employee.setUpdateTime(LocalDateTime.now()); //获得当前登录对象的id Long empId = (Long) request.getSession().getAttribute("empId"); employee.setCreateUser(empId); employee.setUpdateUser(empId); employeeService.save(employee); return R.success("添加员工成功");}
异常捕获
GlobalExceptionHandler
package com.jerry.reggie.common;/** * ClassName: GlobalExceptionHandler * Package: com.jerry.reggie.common * Description: * * @Author jerry_jy * @Create 2023-02-18 16:21 * @Version 1.0 */import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import java.sql.SQLIntegrityConstraintViolationException;/** * 全局异常捕获 */@ControllerAdvice(annotations = {RestController.class, Controller.class})@ResponseBody //要返回json数据时就写@Slf4jpublic class GlobalExceptionHandler { /** * 异常处理方法 * @return */ @ExceptionHandler(SQLIntegrityConstraintViolationException.class) public R<String> exceptionHandler(SQLIntegrityConstraintViolationException exception){ log.error(exception.getMessage()); if (exception.getMessage().contains("Duplicate entry")){ String[] strings = exception.getMessage().split(" "); String msg = strings[2] + "已存在"; return R.error(msg); } return R.error("未知错误"); }}
小结
5.2、员工信息分页查询
需求分析
代码开发
MyBatisPlusConfig配置分页插件
package com.jerry.reggie.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * ClassName: MyBatisPlusConfig * Package: com.jerry.reggie.config * Description: * * @Author jerry_jy * @Create 2023-02-18 17:16 * @Version 1.0 *//** * 配置MP的分页插件 */@Configurationpublic class MyBatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return mybatisPlusInterceptor; }}
/** * 员工信息分页查询 * * @param page * @param pageSize * @param name * @return */@GetMapping("/page")public R<Page> page(int page, int pageSize, String name) { log.info("page = {}, pageSize = {}, name = {}", page, pageSize, name); //这里:只需要new page对象和构造好lambdaQueryWrapper //构造分页构造器 Page<Employee> pageInfo = new Page<>(page, pageSize); //构造条件构造器 LambdaQueryWrapper<Employee> lambdaQueryWrapper = new LambdaQueryWrapper<>(); //添加一个过滤条件 lambdaQueryWrapper.like(StringUtils.isNotEmpty(name), Employee::getName, name); //添加一个排序条件 lambdaQueryWrapper.orderByDesc(Employee::getUpdateTime); //执行查询 employeeService.page(pageInfo, lambdaQueryWrapper); return R.success(pageInfo);}
5.3、启用/禁用员工账号
需求分析
代码编写
编写一个通用的update方法
/** * 根据id修改员工信息 * * @param employee * @return */@PutMappingpublic R<String> update(HttpServletRequest request, @RequestBody Employee employee) { log.info(employee.toString()); Long empId = (Long) request.getSession().getAttribute("empId"); employee.setUpdateTime(LocalDateTime.now()); employee.setUpdateUser(empId); employeeService.updateById(employee); return R.success("更新成功");}
功能测试
原因:JS在处理Long型数据时,只能处理16位,也就是说,2^53次方,超过后就四舍五入,精度损失
功能修复
/** * 扩展mvc消息框架的转换器 * @param converters */@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<" /> 代码编写
/** * 根据id查询员工信息 * * @param id * @return */@GetMapping("/{id}")public R<Employee> getById(@PathVariable Long id) { log.info("根据id 查询员工信息..."); Employee employee = employeeService.getById(id); if (employee != null) { return R.success(employee); } return R.error("没有查询到对应的员工信息");}
5.4、公共字段自动填充
问题分析
代码实现
功能完善
ThreadLocal
BaseContext
package com.jerry.reggie.common;/** * ClassName: BaseContext * Package: com.jerry.reggie.common * Description: * * @Author jerry_jy * @Create 2023-02-19 9:00 * @Version 1.0 *//** * 基于ThreadLocal封装的工具类,用于保存和获取当前登录用户的id */public class BaseContext { private static ThreadLocal<Long> threadLocal= new ThreadLocal<>(); public static void setCurrentId(Long id){ threadLocal.set(id); } public static Long getCurrentId(){ return threadLocal.get(); }}
6、分类管理
6.1、新增菜品分类
需求分析
数据模型
代码开发
6.1、新增菜品的分页查询
需求分析
代码开发
/** * 菜品分页查询 * @param page * @param pageSize * @return */@GetMapping("/page")public R<Page> page(int page, int pageSize){ //分页构造器 Page<Category> categoryPage = new Page<>(); //条件构造器 LambdaQueryWrapper<Category> lambdaQueryWrapper = new LambdaQueryWrapper<>(); //添加排序条件 lambdaQueryWrapper.orderByAsc(Category::getSort); categoryService.page(categoryPage, lambdaQueryWrapper); return R.success(categoryPage);}
6.2、删除分类
需求分析
代码开发
功能完善
GlobalExceptionHandler
/** * 异常处理方法 * @return */@ExceptionHandler(CustomException.class)public R<String> exceptionHandler(CustomException exception){ log.error(exception.getMessage()); return R.error(exception.getMessage());}
CustomException
package com.jerry.reggie.common;/** * ClassName: CustomException * Package: com.jerry.reggie.common * Description: * * @Author jerry_jy * @Create 2023-02-19 11:55 * @Version 1.0 *//** * 自定义业务异常类 */public class CustomException extends RuntimeException{ public CustomException(String message){ super(message); }}
CategoryServiceImpl
package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.jerry.reggie.common.CustomException;import com.jerry.reggie.entity.Category;import com.jerry.reggie.entity.Dish;import com.jerry.reggie.entity.Setmeal;import com.jerry.reggie.mapper.CategoryMapper;import com.jerry.reggie.service.CategoryService;import com.jerry.reggie.service.DishService;import com.jerry.reggie.service.SetmealService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;/** * ClassName: CategoryServiceImpl * Package: com.jerry.reggie.service.impl * Description: * * @Author jerry_jy * @Create 2023-02-19 9:30 * @Version 1.0 */@Servicepublic class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService { @Autowired private DishService dishService; @Autowired private SetmealService setmealService; /** * 根据id删除分类,删除之前需要进行判断 * @param id */ @Override public void remove(Long id) { LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>(); //添加查询条件,根据分类id查询 dishLambdaQueryWrapper.eq(Dish::getCategoryId,id); int count1 = dishService.count(dishLambdaQueryWrapper); //查询当前分类是否关联了菜品,如果已经关联,抛出一个业务异常 if (count1>0){ //已经关联,抛出一个业务异常 throw new CustomException("当前分类下关联了菜品,不能删除"); } //查询当前分类是否关联了套餐,如果已经关联,抛出一个业务异常 LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>(); setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id); int count2 = setmealService.count(setmealLambdaQueryWrapper); if (count2>0){ //已经关联套餐,抛出一个业务异常 throw new CustomException("当前分类下关联了套餐,不能删除"); } //正常删除分类 super.removeById(id); }}
/** * 根据id删除分类 * @param id * @return */ @DeleteMapping public R<String> delete(Long id){ log.info("删除分类:{}",id);// categoryService.removeById(id); categoryService.remove(id); return R.success("分类信息删除成功"); }
6.3、修改分类
需求分析
代码编写
/** * 根据id修改分类信息 * @param category * @return */@PutMappingpublic R<String> update(@RequestBody Category category){ log.info("修改分类信息:{}",category); categoryService.updateById(category); return R.success("修改分类信息成功");}
7、菜品管理
7.1、文件上传下载
文件上传介绍
文件下载介绍
文件上传代码实现
package com.jerry.reggie.controller;import com.jerry.reggie.common.R;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;import java.io.File;import java.io.IOException;import java.util.UUID;/** * ClassName: CommonController * Package: com.jerry.reggie.controller * Description: * * @Author jerry_jy * @Create 2023-02-19 17:19 * @Version 1.0 *//** * 文件上传下载 */@RestController@Slf4j@RequestMapping("/common")public class CommonController { @Value("${reggie.path}")//这里的value不要导包成了lombok,用${}动态取值 private String basePath; /** * 文件上传 * * @param file * @return */ @PostMapping("/upload") public R<String> uploadFile(MultipartFile file) { //file是临时文件,需要转存到指定位置,否则本次请求完成后临时文件会删除 log.info(file.toString()); //获取原始文件名 String originalFilename = file.getOriginalFilename(); //获取原始文件名的后缀名,这里是带点的 String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); //使用UUID重新生成文件名,防止文件名称重复造成的文件覆盖 String fileName = UUID.randomUUID().toString() + suffix; //创建一个目录对象 File dir = new File(basePath); if (!dir.exists()){ //目录不存在,创建一个 dir.mkdirs(); } try { //将临时文件转存到指定位置 file.transferTo(new File(basePath + fileName)); } catch (IOException e) { throw new RuntimeException(e); } return R.success(fileName); }}
文件下载代码实现
/** * 文件下载 * * @param name * @param response */@GetMapping("/download")public void download(String name, HttpServletResponse response) { try { // 输入流,通过输入流读取文件内容 FileInputStream fileInputStream = new FileInputStream(new File(basePath + name)); //输出流,通过输出流将文件写回浏览器,在浏览器显示图片 ServletOutputStream outputStream = response.getOutputStream(); //设置输出流的类型为图片 response.setContentType("image/jpeg"); int len = 0; byte[] bytes = new byte[1024]; while ((len = fileInputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, len); outputStream.flush(); } // 关闭资源 outputStream.close(); fileInputStream.close(); } catch (Exception e) { throw new RuntimeException(e); }}
7.2、新增菜品
需求分析
数据模型
代码开发
由于新增菜品涉及到多张表的插入操作,因此需要在Service业务层中单独写一个save方法
DishServiceImpl
package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.jerry.reggie.dto.DishDto;import com.jerry.reggie.entity.Dish;import com.jerry.reggie.entity.DishFlavor;import com.jerry.reggie.mapper.DishFlavorMapper;import com.jerry.reggie.mapper.DishMapper;import com.jerry.reggie.service.DishFlavorService;import com.jerry.reggie.service.DishService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import java.util.List;import java.util.stream.Collectors;/** * ClassName: DishServiceImpl * Package: com.jerry.reggie.service.impl * Description: * * @Author jerry_jy * @Create 2023-02-19 10:53 * @Version 1.0 */@Service@Slf4jpublic class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService { @Autowired private DishFlavorService dishFlavorService; /** * 新增菜品同时保存口味数据 * @param dishDto */ @Transactional @Override public void saveWithFlavor(DishDto dishDto) { //保存菜品基本信息到菜品表dish this.save(dishDto); Long dishId = dishDto.getId(); //菜品口味 List<DishFlavor> flavors = dishDto.getFlavors(); flavors = flavors.stream().map((item) -> { item.setDishId(dishId); return item; }).collect(Collectors.toList()); //保存菜品口味到到菜品口味表dish_flavor dishFlavorService.saveBatch(flavors); }}
DishController
package com.jerry.reggie.controller;import com.jerry.reggie.common.R;import com.jerry.reggie.dto.DishDto;import com.jerry.reggie.entity.Dish;import com.jerry.reggie.service.DishFlavorService;import com.jerry.reggie.service.DishService;import lombok.extern.java.Log;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;/** * ClassName: DishController * Package: com.jerry.reggie.controller * Description: * * @Author jerry_jy * @Create 2023-02-19 19:11 * @Version 1.0 */@Slf4j@RestController@RequestMapping("/dish")public class DishController { @Autowired DishFlavorService dishFlavorService; @Autowired DishService dishService; /** * 新增菜品 * @param dishDto * @return */ @PostMapping public R<String> addMeal(@RequestBody DishDto dishDto){ log.info(dishDto.toString()); dishService.saveWithFlavor(dishDto); return R.success("保存成功"); }}
7.3、菜品信息分页查询
需求分析
代码开发
难点
这里的分页查询涉及到2个对象的拷贝复赋值问题,使用BeanUtils.copyProperties()来完成操作的
把Dish对象赋值给DishDto对象,并设置上categoryName
流式处理的表达式是重点!!!
/** * 菜品信息--分页查询 * * @param page * @param pageSize * @param name * @return */@GetMapping("/page")public R<Page> page(int page, int pageSize, String name) { //分页构造器 Page<Dish> pageInfo = new Page<>(page, pageSize); Page<DishDto> dishDtoPage = new Page<>(); //条件构造器 LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>(); //添加过滤条件 lambdaQueryWrapper.like(name != null, Dish::getName, name); //添加过滤条件 lambdaQueryWrapper.orderByDesc(Dish::getUpdateTime); dishService.page(pageInfo, lambdaQueryWrapper); //对象拷贝 BeanUtils.copyProperties(pageInfo, dishDtoPage,"records"); List<Dish> records = pageInfo.getRecords(); List<DishDto> list = records.stream().map((item) -> { DishDto dishDto = new DishDto(); //对象拷贝 BeanUtils.copyProperties(item, dishDto); Long categoryId = item.getCategoryId();//分类id Category category = categoryService.getById(categoryId);//分类对象 if (category!=null){ String categoryName = category.getName(); dishDto.setCategoryName(categoryName); } return dishDto; }).collect(Collectors.toList()); dishDtoPage.setRecords(list); return R.success(dishDtoPage);}
7.4、修改菜品
需求分析
代码开发
controller
/** * * @param dishDto * @return */@PutMappingpublic R<String> updateMeal(@RequestBody DishDto dishDto){ log.info(dishDto.toString()); dishService.updateWithFlavor(dishDto); return R.success("保存菜品成功");}
DishServiceImpl
/** * 更新菜品信息,同时更新对应的口味信息 * * @param dishDto */@Override@Transactionalpublic void updateWithFlavor(DishDto dishDto) { //更新dish表基本信息 this.updateById(dishDto); //先清理当前菜品对应的口味信息---dish_flavor表的 delete 操作 LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(DishFlavor::getDishId, dishDto.getId()); dishFlavorService.remove(lambdaQueryWrapper); //再添加当前提交过来的口味数据--dish_flavor表的 insert 操作 List<DishFlavor> flavors = dishDto.getFlavors(); flavors = flavors.stream().map((item) -> { item.setDishId(dishDto.getId()); return item; }).collect(Collectors.toList()); dishFlavorService.saveBatch(flavors);}
7.5、修改菜品的停/起售状态
DishController
/** * 修改菜品的 停/启 售状态 * * @param ids * @return */ @PostMapping("/status/{status}") public R<Dish> status(long ids) { Dish dish = dishService.getById(ids); dishService.setStatus(dish); return R.success(dish); }
DishServiceImpl
/** * 修改菜品的停/启售状态 * @param dish */@Overridepublic void setStatus(Dish dish) { if (dish.getStatus()==1){ dish.setStatus(0); }else { dish.setStatus(1); } this.updateById(dish);}
7.6、删除菜品
/** * 菜品管理--批量删除菜品--跟单个删除一样的,复用同一份代码 * @param ids * @return */ @DeleteMapping public R<String> delete(Long[] ids){ for (Long id : ids) { dishService.delete(id); } return R.success("删除菜品成功!"); }
8、套餐管理
8.1、新增套餐
需求分析
数据模型
代码开发
DishController
/** * 根据条件来查询对应的菜品数据 * @param dish * @return */@GetMapping("/list")public R<List<Dish>> list(Dish dish){ //构造查询条件 LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId()); //查询状态为1,启售状态 lambdaQueryWrapper.eq(Dish::getStatus,1); //添加排序条件 lambdaQueryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime); List<Dish> list = dishService.list(lambdaQueryWrapper); return R.success(list);}
SetmealDishController
/** * 新增套餐 * @param setmealDto * @return */@PostMappingpublic R<String> save(@RequestBody SetmealDto setmealDto){ log.info("套餐信息:{}",setmealDto.toString()); setmealService.saveWithDish(setmealDto); return R.success("新增套餐成功");}
SetmealServiceImpl
/** * 新增套餐,同时需要保存套餐和菜品的关联关系 * @param setmealDto */@Override@Transactionalpublic void saveWithDish(SetmealDto setmealDto) { //保存套餐的基本信息 操作setmeal 执行insert this.save(setmealDto); List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes(); setmealDishes.stream().map((item)->{ item.setSetmealId(setmealDto.getId()); return item; }).collect(Collectors.toList()); //保存套餐和菜品的关联信息,操作setmeal_dish,执行insert setmealDishService.saveBatch(setmealDishes);}
8.2、套餐信息分页查询
需求分析
代码开发
/** * 套餐管理--套餐信息分页查询 * @param page * @param pageSize * @param name * @return */@GetMapping("/page")public R<Page> page(int page, int pageSize, String name) { //分页构造器 Page<Setmeal> pageInfo = new Page<>(page, pageSize); Page<SetmealDto> dtoPage = new Page<>(); //条件构造器 LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>(); //添加过滤条件 lambdaQueryWrapper.like(name != null, Setmeal::getName, name); //添加过滤条件 lambdaQueryWrapper.orderByDesc(Setmeal::getUpdateTime); setmealService.page(pageInfo, lambdaQueryWrapper); //对象拷贝 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);}
8.3、删除套餐
需求分析
代码开发
SetmealController
/** * (批量)删除套餐 * * @param ids * @return */@DeleteMappingpublic R<String> delete(@RequestParam List<Long> ids) { log.info("id: {}", ids); setmealService.removeWithDish(ids); return R.success("套餐数据删除成功");}
SetmealServiceImpl
/** * 删除套餐,同时输出套餐和菜品关联的数据 * * @param ids */@Overridepublic void removeWithDish(List<Long> ids) { // 先查询套餐状态,确实是否可以删除 // select count(*) from setmeal where id in (1, 2, 3) and status = 1; LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.in(Setmeal::getId, ids); lambdaQueryWrapper.eq(Setmeal::getStatus, 1); int count = this.count(lambdaQueryWrapper); if (count > 0) { // 如果不能删除,抛出一个业务异常 throw new CustomException("套餐正在售卖中,不能删除"); } // 如果可以删除,先删除套餐表中的数据-- setmeal this.removeByIds(ids); //再删除关系表中的数据-- setmeal_dish // delete from setmeal_dish where id in (1, 2, 3); LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(SetmealDish::getSetmealId, ids); setmealDishService.remove(queryWrapper);}
8.4、修改套餐
SetmealController
/** * 根据id查询套餐信息和对应的套餐内容---回显套餐信息 * @param id * @return */ @GetMapping("/{id}") public R<SetmealDto> getMealDtoById(@PathVariable long id){ SetmealDto setmealDto = setmealService.getByIdWithSetmeal(id); return R.success(setmealDto); } /** * 修改套餐信息,并保存 * @param setmealDto * @return */ @PutMapping public R<String> updateSetmeal(@RequestBody SetmealDto setmealDto) { log.info(setmealDto.toString()); setmealService.updateWithSetmeal(setmealDto); return R.success("保存菜品成功"); }
SetmealService
//根据id查询套餐信息和对应的套餐内容---回显套餐信息SetmealDto getByIdWithSetmeal(long id);//修改套餐信息,并保存void updateWithSetmeal(SetmealDto setmealDto);
SetmealServiceImpl
/** * 根据id查询套餐信息和对应的套餐内容---回显套餐信息 * * @param id * @return */ @Override public SetmealDto getByIdWithSetmeal(long id) { //查询套餐基本信息,从setmeal表查询 Setmeal setMeal = this.getById(id); SetmealDto setmealDto = new SetmealDto(); BeanUtils.copyProperties(setMeal, setmealDto); //查询当前套餐对应的套餐信息,从setmeal_dish表中查 LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(SetmealDish::getSetmealId, setMeal.getId()); List<SetmealDish> setmealDishes = setmealDishService.list(lambdaQueryWrapper); setmealDto.setSetmealDishes(setmealDishes); return setmealDto; } /** * 修改套餐信息,并保存 * * @param setmealDto */ @Override @Transactional public void updateWithSetmeal(SetmealDto setmealDto) { //更新 setmeal 表基本信息 this.updateById(setmealDto); //先清理当前套餐对应的套餐信息--- setmeal_dish 表的 delete 操作 LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(SetmealDish::getSetmealId, setmealDto.getId()); setmealDishService.remove(lambdaQueryWrapper); //再添加当前提交过来的套餐数据-- setmeal_dish表的 insert 操作 List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes(); setmealDishes = setmealDishes.stream().map((item) -> { item.setSetmealId(setmealDto.getId()); return item; }).collect(Collectors.toList()); setmealDishService.saveBatch(setmealDishes); }
8.5、停售、启售套餐
SetmealController
/** * 修改套餐的 停/启 售状态 * @param ids * @return */@PostMapping("/status/{status}")public R<Setmeal> status(long ids) { Setmeal setmeal = setmealService.getById(ids); setmealService.setStatus(setmeal); return R.success(setmeal);}
SetmealServiceImpl
/** * 修改套餐的 停/启 售状态 * @param setmeal */@Overridepublic void setStatus(Setmeal setmeal) { if (setmeal.getStatus() == 1) { setmeal.setStatus(0); } else { setmeal.setStatus(1); } this.updateById(setmeal);}
9、前端–手机验证码登录
9.1、短信发送
阿里云短信服务
https://dysms.console.aliyun.com/quickstart?spm=5176.25163407.domtextsigncreate-index-1ec3c_58c50_0.1.5097bb6euk5OnF
设置签名
https://dysms.console.aliyun.com/domestic/text/sign
切换到【模板管理】标签页
添加模板详情
设置AccessKey
创建用户
自己保存好【AccessKey Secret】
添加权限
购买短信免费试用包
代码开发
pom
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.5.16</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <version>2.1.0</version> </dependency>
导入utils工具类
9.2、手机验证码登录
需求分析
数据模型
代码开发
移动端页面放行的请求
LoginCheckFilter
//4-2、判断移动端用户登录状态,如果已登录,则直接放行if (request.getSession().getAttribute("user") != null) { log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("user")); Long userId = (Long) request.getSession().getAttribute("user"); BaseContext.setCurrentId(userId); filterChain.doFilter(request, response); return;}
UserController
package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.jerry.reggie.common.R;import com.jerry.reggie.entity.User;import com.jerry.reggie.service.UserService;import com.jerry.reggie.utils.SMSUtils;import com.jerry.reggie.utils.ValidateCodeUtils;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang.StringUtils;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 javax.servlet.http.HttpSession;import java.util.Map;/** * ClassName: UserController * Package: com.jerry.reggie.controller * Description: * * @Author jerry_jy * @Create 2023-02-21 18:00 * @Version 1.0 */@RestController@Slf4j@RequestMapping("/user")public class UserController { @Autowired private UserService userService; /** * 发送手机验证码短信 * @param user * @return */ @PostMapping("/sendMsg") public R<String> sendMsg(@RequestBody User user, HttpSession session){ //获取手机号 String phone = user.getPhone(); if (StringUtils.isNotEmpty(phone)){ //生成随机的4位验证码 String code = ValidateCodeUtils.generateValidateCode(4).toString(); log.info("code={}",code); //调用阿里云提供的短信服务API完成短信发送 // 没有买短信包,就不发手机短信了// SMSUtils.sendMessage("reggie外卖","SMS_270890116",phone,code); // 需要将生成的验证码保存到 session 中 session.setAttribute(phone,code); return R.success("手机短信验证码发送成功"); } return R.error("短信发送失败"); } /** * 移动端用户登录 * @param map * @param session * @return */ @PostMapping("/login") public R<User> login(@RequestBody Map map, HttpSession session){ log.info(map.toString()); //获取手机号 String phone = map.get("phone").toString(); // 获取验证码 String code = map.get("code").toString(); // 从session中获取保存的验证码 Object codeInSession = session.getAttribute(phone); //进行验证码的比对 (页面提交过来的验证码和session中保存的验证码进行比对) if (codeInSession != null && codeInSession.equals(code)){ // 如果比对成功,说明登录成功 LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(User::getPhone,phone); User user = userService.getOne(lambdaQueryWrapper); if (user==null){ // 判断当前手机号是否为新用户,如果是新用户就能自动完成注册 user= new User(); user.setPhone(phone); user.setStatus(1); userService.save(user); } session.setAttribute("user", user.getId()); return R.success(user); } return R.error("登录失败"); }}
10、前端–导入用户地址簿
需求分析
数据模型
代码开发
AddressBookController
package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;import com.jerry.reggie.common.BaseContext;import com.jerry.reggie.common.R;import com.jerry.reggie.entity.AddressBook;import com.jerry.reggie.service.AddressBookService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.List;/** * ClassName: AddressBookController * Package: com.jerry.reggie.controller * Description: * * @Author jerry_jy * @Create 2023-02-21 20:42 * @Version 1.0 *//** * 地址簿管理 */@Slf4j@RestController@RequestMapping("/addressBook")public class AddressBookController { @Autowired private AddressBookService addressBookService; /** * 新增 */ @PostMapping public R<AddressBook> save(@RequestBody AddressBook addressBook) { addressBook.setUserId(BaseContext.getCurrentId()); log.info("addressBook:{}", addressBook); addressBookService.save(addressBook); return R.success(addressBook); } /** * 设置默认地址 */ @PutMapping("default") public R<AddressBook> setDefault(@RequestBody AddressBook addressBook) { log.info("addressBook:{}", addressBook); LambdaUpdateWrapper<AddressBook> wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(AddressBook::getUserId, BaseContext.getCurrentId()); wrapper.set(AddressBook::getIsDefault, 0); //SQL:update address_book set is_default = 0 where user_id = " /> 代码开发
展示flavor口味信息
// 前端需要展示flavor口味信息@GetMapping("/list")public R<List<DishDto>> list(Dish dish) { //构造查询条件 LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId()); //查询状态为1,启售状态 lambdaQueryWrapper.eq(Dish::getStatus, 1); //添加排序条件 lambdaQueryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime); List<Dish> list = dishService.list(lambdaQueryWrapper); List<DishDto> dishDtoList = list.stream().map((item) -> { DishDto dishDto = new DishDto(); //对象拷贝 BeanUtils.copyProperties(item, dishDto); Long categoryId = item.getCategoryId();//分类id Category category = categoryService.getById(categoryId);//分类对象 if (category != null) { String categoryName = category.getName(); dishDto.setCategoryName(categoryName); } //当前菜品id Long dishId = item.getId(); LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(DishFlavor::getDishId,dishId); List<DishFlavor> dishFlavorList = dishFlavorService.list(queryWrapper); dishDto.setFlavors(dishFlavorList); return dishDto; }).collect(Collectors.toList()); return R.success(dishDtoList);}
套餐信息展示
/** * 根据条件查询套餐数据 * * @param setmeal * @return */@GetMapping("/list")public R<List<Setmeal>> list(Setmeal setmeal) { //构造查询条件 LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId()); //查询状态为1,启售状态 lambdaQueryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus()); //添加排序条件 lambdaQueryWrapper.orderByDesc(Setmeal::getUpdateTime); List<Setmeal> list = setmealService.list(lambdaQueryWrapper); return R.success(list);}
12、前端–购物车
需求分析
数据模型
代码开发
购物车需要实现查看/增加/减少/清空商品
package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.jerry.reggie.common.BaseContext;import com.jerry.reggie.common.R;import com.jerry.reggie.entity.ShoppingCart;import com.jerry.reggie.service.ShoppingCartService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.time.LocalDateTime;import java.util.List;/** * ClassName: ShoppingCartController * Package: com.jerry.reggie.controller * Description: * * @Author jerry_jy * @Create 2023-02-22 10:14 * @Version 1.0 */@RestController@RequestMapping("/shoppingCart")@Slf4jpublic class ShoppingCartController { @Autowired private ShoppingCartService shoppingCartService; /** * 添加购物车 * * @param shoppingCart * @return */ @PostMapping("/add") public R<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart) { log.info("购物车数据封装,{}", shoppingCart.toString()); // 设置用户id,指定当前是哪个用户的购物车数据 Long currentId = BaseContext.getCurrentId(); shoppingCart.setUserId(currentId); Long dishId = shoppingCart.getDishId(); LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(ShoppingCart::getUserId, shoppingCart.getUserId()); if (dishId != null) { // 添加到购物车的是菜品 lambdaQueryWrapper.eq(ShoppingCart::getDishId, dishId); } else { // 添加到购物车的是套餐 lambdaQueryWrapper.eq(ShoppingCart::getSetmealId, shoppingCart.getSetmealId()); } // 查询当前菜品或套餐是否在购物车中, ShoppingCart cart = shoppingCartService.getOne(lambdaQueryWrapper); if (cart != null) { //如果已经存在,就在原来数量基础上加一 Integer number = cart.getNumber(); cart.setNumber(number + 1); shoppingCartService.updateById(cart); } else { // 如果不存在,则x添加到购物车,数量默认就是 1 shoppingCart.setNumber(1); shoppingCart.setCreateTime(LocalDateTime.now()); shoppingCartService.save(shoppingCart); cart = shoppingCart; } return R.success(cart); } /** * 减少购物车的菜品 * * @return */ @PostMapping("/sub") public R<ShoppingCart> sub(@RequestBody ShoppingCart shoppingCart) { log.info("购物车数据封装,{}", shoppingCart.toString()); LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId()); if (shoppingCart.getDishId() != null) { // 减少到购物车的是菜品 lambdaQueryWrapper.eq(ShoppingCart::getDishId, shoppingCart.getDishId()); } else { // 减少到购物车的是套餐 lambdaQueryWrapper.eq(ShoppingCart::getSetmealId, shoppingCart.getSetmealId()); } // 查询当前菜品或套餐是否在购物车中, ShoppingCart cart = shoppingCartService.getOne(lambdaQueryWrapper); //如果已经存在并且数量 > 1,就在原来数量基础上 - 1 if ((cart.getNumber() > 1)) { Integer number = cart.getNumber(); cart.setNumber(number - 1); shoppingCartService.updateById(cart); } else { //移除改菜品或套餐 shoppingCartService.remove(lambdaQueryWrapper); } return R.success(cart); } /** * 清空购物车 * * @return */ @DeleteMapping("/clean") public R<String> clean() { LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId()); shoppingCartService.remove(lambdaQueryWrapper); return R.success("清空购物车成功"); } /** * 查看购物车 * * @return */ @GetMapping("/list") public R<List<ShoppingCart>> list() { log.info("查看购物车..."); LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId()); lambdaQueryWrapper.orderByAsc(ShoppingCart::getCreateTime); List<ShoppingCart> list = shoppingCartService.list(lambdaQueryWrapper); return R.success(list); }}
13、前端–用户下单
需求分析
数据模型
代码开发
OrderController
package com.jerry.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.jerry.reggie.common.R;import com.jerry.reggie.entity.Orders;import com.jerry.reggie.service.OrderService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;/** * ClassName: OrderController * Package: com.jerry.reggie.controller * Description: * * @Author jerry_jy * @Create 2023-02-22 13:53 * @Version 1.0 */@Slf4j@RestController@RequestMapping("/order")public class OrderController { @Autowired private OrderService orderService; /** * 用户下单 * @param orders * @return */ @PostMapping("/submit") public R<String> submit(@RequestBody Orders orders){ log.info("订单数据:{}",orders); orderService.submit(orders); return R.success("下单成功"); } /** * 订单查询 * @param page * @param pageSize * @return */ @GetMapping("/userPage") public R<Page> userPage(int page, int pageSize){ //分页构造器 Page<Orders> pageInfo = new Page<>(); //条件构造器 LambdaQueryWrapper<Orders> lambdaQueryWrapper = new LambdaQueryWrapper<>(); //添加排序条件 lambdaQueryWrapper.orderByDesc(Orders::getOrderTime); orderService.page(pageInfo, lambdaQueryWrapper); return R.success(pageInfo); }}
OrderService
package com.jerry.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;import com.jerry.reggie.entity.Orders;/** * ClassName: OrderService * Package: com.jerry.reggie.service * Description: * * @Author jerry_jy * @Create 2023-02-22 13:52 * @Version 1.0 */public interface OrderService extends IService<Orders> { //用户下单 void submit(Orders orders);}
OrderServiceImpl
package com.jerry.reggie.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.toolkit.IdWorker;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.jerry.reggie.common.BaseContext;import com.jerry.reggie.common.CustomException;import com.jerry.reggie.entity.*;import com.jerry.reggie.mapper.OrderMapper;import com.jerry.reggie.service.*;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import java.math.BigDecimal;import java.time.LocalDateTime;import java.util.List;import java.util.concurrent.atomic.AtomicInteger;import java.util.stream.Collectors;/** * ClassName: OrderServiceImpl * Package: com.jerry.reggie.service.impl * Description: * * @Author jerry_jy * @Create 2023-02-22 13:52 * @Version 1.0 */@Servicepublic class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService { @Autowired private ShoppingCartService shoppingCartService; @Autowired private UserService userService; @Autowired private AddressBookService addressBookService; @Autowired private OrderDetailService orderDetailService; /** * 用户下单 * @param orders */ @Transactional @Override public void submit(Orders orders) { // 获取用户id Long userId = BaseContext.getCurrentId(); // 查询当前用户购物车的数据 LambdaQueryWrapper<ShoppingCart> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(ShoppingCart::getUserId,userId); List<ShoppingCart> shoppingCartList = shoppingCartService.list(lambdaQueryWrapper); if (shoppingCartList == null || shoppingCartList.size()==0){ throw new CustomException("购物车为空,不能下单"); } // 查询用户数据 User user = userService.getById(userId); // 查询地址数据 Long addressBookId = orders.getAddressBookId(); AddressBook addressBook = addressBookService.getById(addressBookId); if (addressBook == null){ throw new CustomException("用户地址信息有误,不能下单"); } long orderId = IdWorker.getId();//生成订单号 AtomicInteger amount = new AtomicInteger(0); List<OrderDetail> orderDetails= shoppingCartList.stream().map((item)->{ OrderDetail orderDetail = new OrderDetail(); orderDetail.setOrderId(orderId); orderDetail.setNumber(item.getNumber()); orderDetail.setDishFlavor(item.getDishFlavor()); orderDetail.setDishId(item.getDishId()); orderDetail.setSetmealId(item.getSetmealId()); orderDetail.setName(item.getName()); orderDetail.setImage(item.getImage()); orderDetail.setAmount(item.getAmount()); amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue()); return orderDetail; }).collect(Collectors.toList()); orders.setId(orderId); orders.setOrderTime(LocalDateTime.now()); orders.setCheckoutTime(LocalDateTime.now()); orders.setStatus(2); orders.setAmount(new BigDecimal(amount.get()));//总金额 orders.setUserId(userId); orders.setNumber(String.valueOf(orderId)); orders.setUserName(user.getName()); orders.setConsignee(addressBook.getConsignee()); orders.setPhone(addressBook.getPhone()); orders.setAddress((addressBook.getProvinceName() == null " />Gitee
https://gitee.com/jinyang-jy/reggie.git
Github
https://github.com/Jerry-jy/reggie.git
项目所需资料
链接:https://pan.baidu.com/s/182tTb1rmGkTCbq9aXrbjMg?pwd=2022
提取码:2022