代码拉取完成,页面将自动刷新
同步操作将从 王笔剑/javajun_reggie 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
瑞吉外卖项目环境搭建: 1.数据库环境准备 方式一:图形化工具 1.1:创建数据库 reggie 1.2:执行SQL脚本 02-资料\01-数据模型\db_reggie.sql 方式二:DOS命令行实现【了解】 1.1:登录MySQL数据库服务器 mysql-uroot -p1234 1.2:创建数据库 create database reggie; 1.3:切换数据库 use reggie; 1.4:执行SQL脚本 source D:\db_reggie.sql 2.项目环境搭建 1.创建一个普通的maven工程 项目名称为reggie 2.使用资料中提供的pom.xml替换项目中的pom.xml 3.拷贝资料中提供的application.yml到项目的resources目录下 4.编写启动类 @Slf4j @SpringBootApplication public class ReggieApplication { public static void main(String[] args) { SpringApplication.run(ReggieApplication.class,args); log.info("项目启动成功!"); } } 5.OK 可以测试了 添加静态资源到项目中 方式一:【后续使用会有问题】 1.1:直接在resources目录下创建static目录 将静态资源放入static目录中即可 原理: 就是SpringBoot自动配置,SpringBoot自动做了静态资源处理 如果发现你请求的是静态资源 会自动的去到static目录下找对应的资源 不推荐原因:如果后面还需要对SpringMVC做配置修改,则会导致SpringBoot中关于SpringMVC的一些自动配置失效 就会导致访问404 方式二:【推荐】 2.1:直接将静态资源放到resources目录下 【此时当你访问静态资源时SpringBoot并不知道去哪里找】 2.2:配置静态资源映射处理 告诉静态资源请求 去哪里找到对应的资源 @Slf4j @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { //配置静态资源映射 @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { log.info("开启静态资源映射..."); //通过addResourceHandler添加映射路径,然后通过addResourceLocations来指定路径。 //addResourceHandler指的是对外暴露的访问路径,addResourceLocations指的是文件放置的目录路径 registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/"); registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/"); } } 瑞吉外卖项目功能开发: day01: 员工模块: 后台员工登录 需求分析: 1.前端页面:/backend/page/login/login.html 2.请求流程:进入到登录页面 ---》输入用户名和密码---》点击登录按钮---》发送登录请求---》后端服务器接收请求进行处理并且返回结果 3.接口设计: 接口地址:/employee/login 请求方式:POST 接口入参:{username: "admin", password: "1213456"} json格式 接口响应:员工信息Employee对象 R<Employee> 4.数据模型:Employee表 代码准备: 1.前端:表姐已完成 login.html登录页面 login.js --->封装登录请求 2.后端: bean: Employee dao: EmployeeDao接口 service: EmployeeService接口、EmployeeServiceImpl实现类 controller: EmployeeController commons: R 返回结果类 思路分析: 在EmployeeController定义一个登录的方法 1、将页面提交的密码password进行md5加密处理 2、根据页面提交的用户名username查询数据库 3、如果没有查询到则返回登录失败结果 4、密码比对,如果不一致则返回登录失败结果 5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果 6、登录成功,将员工id存入Session并返回登录成功结果 后台员工退出 需求分析: 1.前端页面:/backend/index.html 2.请求流程:登录后进入到首页---》点击退出按钮---》发送退出登录请求---》后端接收请求处理并响应 3.接口设计: 接口地址:/employee/logout 请求方式:POST 接口入参:无 接口响应:R<String> 退出成功|失败 4.数据模型:无 思路分析: 在EmployeeController定义一个退出方法 1.清空session的数据 2.返回结果 完善登录功能: 问题分析: 前面我们已经完成了后台系统的员工登录功能开发,但是还存在一个问题:用户如果不登录,直接访问系统首页面,照样可以正常访问。 这种设计并不合理,我们希望看到的效果应该是,只有登录成功后才可以访问系统中的页面,如果没有登录则跳转到登录页面。 解决方案: 那么,具体应该怎么实现呢? 答案就是使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面 使用过滤器解决 实现分析: 1、创建自定义过滤器LoginCheckFilter 2、在启动类上加入注解@ServletComponentScan 作用:可以让过滤通过@WebFileter自动注册到spring容器中 3、完善过滤器的处理逻辑: 1、获取本次请求的URI 2、判断本次请求是否需要处理 3、如果不需要处理,则直接放行 4、判断登录状态,如果已登录,则直接放行 5、如果未登录则返回未登录结果 新增员工: 需求分析: 1.前端页面:/backend/page/member/add.html 2.请求流程:登录进入到后台首页员工管理页面 ---》点击添加员工按钮---》进入到添加员工页面add.html---》完善员工信息---》点击保存---》 发送新增员工请求---》后端服务接收请求进行处理并响应 3.接口设计: 接口路径:/employee 请求方式:POST 接口入参:{name: "张三", phone: "17700001111", sex: "1", idNumber: "101010199910101010", username: "zhangsan"} json格式 用Employee对象封装 接口响应:R<String> 新增员工成功|失败 4.数据模型:Employee表 实现思路: 1.前端:已完成 2.后端: controller: 在EmployeeController中定义一个新增员工的方法: 1.补齐员工相关字段 2.调用service的保存方法 3.返回结果 service: mp提供的新增方法 dao: mp提供的新增方法 存在问题: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'zhangsan' for key 'idx_username' 原因:employee表给username设置了唯一约束,在添加员工的时候,不能添加重复的用户名 解决:在添加员工之前做一个校验--判断数据库中是否存在该username day02: 员工模块: 员工分页查询: 需求分析: 1.前端页面:/backend/page/member/list.html 2.请求流程:员工登录之后进入到首页index.html---》默认打开员工管理页面---》一打开页面就触发分页查询请求---》后端服务器接收请求处理并响应 3.接口设计: 接口地址:/employee/page?page=1&pageSize=10&name=zhangsan 请求方式:GET 接口入参:page=1&pageSize=10 name参数可选参数 接口响应:分页对象 R<Page<Employee>> 需要records 和 total 4.数据模型:Employee表 思路分析: controller: 在EmployeeController定义一个员工分页查询的方法: 0.添加分页拦截器 1.获取前端的参数page=1&pageSize=10&name=xxx 2.设置查询条件 3.创建分页对象 4.调用service的分页接口,将分页对象以及查询对象一起传递给分页接口 5.返回结果给前端 service: MP已经提供了分页接口 dao: MP已经提供了分页接口 员工启用|禁用: 需求分析: 1.前端页面:/backend/page/member/list.html 2.请求流程:管理员登录进入到员工管理页面---》触发禁用|启用按钮---》发送请求给后端---》后端接收请求进行处理并响应 3.接口设计: 接口地址:/employee 请求方式:PUT 接口入参:{id: 1611287037493588000, status: 0} 接口响应:R<String> 修改状态成功|失败 4.数据模型:Employee表 思路分析: 1.前端:已实现 2.后端: controller: 在EmployeeController中定义一个更新方法: 1.接收前端的参数 2.调用service根据id查询数据库Employee表 3.修改状态 4.返回修改结果 service: MP已经提供查询方法 dao: MP已经提供查询方法 问题分析: 启用|禁用的时候,未生效,数据库中的数据也没有变化。SQL执行的结果是更新的数据行数为0,仔细观察id的值,和数据库中对应记录的id值并不相同 原因:js对long型数据进行处理时丢失精度,只精确16位,导致提交的id和数据库中的id不一致 解决:在服务端给页面响应json数据时进行处理,将long型数据统一转为String字符串 具体步骤: 1)提供对象转换器基于Jackson进行Java对象到json数据的转换(资料中已经提供,直接复制到项目中使用)JacksonObjectMapper, 2)在WebMvcConfig配置类中扩展Spring mvc的消息转换器,在此消息转换器中使用提供的对象转换器进行Java对象到json数据的转换 员工编辑: 需求分析: 1.前端页面:/backend/page/member/add.html 2.请求流程:员工登录到系统首页---》点击编辑按钮---》立即触发一个请求【根据id查询员工信息】---》后端接收请求响应信息回显到页面---》 修改里面的员工信息---》点击保存按钮---》触发一个请求【更新员工信息】---》后端接收请求响应结果给前端 3.接口设计: 3.1 根据id查询员工信息 【待实现】 接口地址:/employee/{id} 请求方式:GET 接口入参:路径参数 员工id 接口响应:员工信息 R<Employee> 3.2 更新员工信息 【已完成】 接口地址:/employee 请求方式:PUT 接口入参:Employee接收 接口响应:R<String> 修改成功|失败 4.数据模型:Employee表 思路分析: 前端:已完成 后端: 根据id查询员工信息 controller: 在EmployeeController中定义一个根据id查询方法: 1.调用service的根据id查询接口 2.返回查询结果给前端 service: MP已经提供 dao: MP已经提供 编辑员工时,修改用户名为已存在的,会出现问题: ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'lisi' for key 'idx_username' 解决: 1.在更新之前做一下用户名判断,根据username查询数据库,并且排除本身的数据【根据id排除】 2.如果查出来的数据不为空,就代表这个用户名已经存在,直接返回错误结果 3.如果数据为空,可以提交更新操作 公共字段自动填充: 问题:每张表中都会存在公共字段,每次新增修改时,手动设置,代码冗余,比较繁琐,容易遗忘 解决:MyBatisPlus公共字段自动填充功能 MP工作原理:使用MyBatisPlus进行新增时,识别到类上属性有@TableField注解并且指定了填充策略为INSERT时, 就会执行MyMetaObjectHandler类中insertFill方法为公共字段赋值 实现步骤: 1.在实体类中公共字段对应的属性上打上@TableField注解 设置自动填充策略 【INSERT、UPDATE、INSERT_UPDATE】 2.自定义一个类,实现MetaObjectHandler接口,设置自动填充时公共字段的值,需要添加@Component注解,将其交由spring容器管理 创建人和更新人字段自动填充: 方式一:使用HttpSession对象 session.getAttribute("employeeId") 方式二:使用ThreadLocal对象 ThreadLocal:是一个线程工具类 作用:可以实现在一个线程间进行数据共享,线程之外获取不到 相当于request域对象【一次请求】 使用: set(Object value):设置线程间共享的数据 get():获取线程间共享的数据 原理: 相当于为每一个线程 创建一个Map集合对象 线程id作为key,要共享的数据作为value 通过ThreadLocal实现登录用户id在一个线程间共享 实现关键点:先在LoginCheckFilter中获取登录成功的员工id存入ThreadLocal中,在设置公共字段值时再从ThreadLocal中取出来 具体实现步骤: 1.基于ThreadLocal定义工具类BaseContext 2.在LoginCheckFilter中获取登录成功的员工id存入ThreadLocal中 3.在设置公共字段值时再从ThreadLocal中取出登录的员工id 分类模块: 新增分类: 需求分析 1.前端页面:/backend/page/category/list.html 2.请求流程:进入分类管理页面--》点击新增菜品或者新增套餐---》填写分类名称和排序---》点击确定发送请求---》后端处理响应 3.接口设计: 接口地址:/category 请求方式:POST 接口入参:{name: "辣椒炒肉", type: "1", sort: "1"} Category对象封装 接口响应:R<String> 新增成功|失败 4.数据模型:Category 代码准备: bean:Category dao: CategoryDao接口 service: CategoryService接口、CategoryServiceImpl controller: CategoryController 实现思路: 1.前端:已完成 2.后端: controller: 在CategoryController中定义一个新增方法: 0.补齐字段信息【用Mp的字段自动填充功能,这一步省略】 1.调用service的保存方法保存数据到表中 2.返回结果 service: MP提供 dao: MP提供 分类分页查询: 需求分析: 1.前端页面:/backend/page/category/list.html 2.请求流程:员工登录之后进入到首页index.html---》进入到分类管理页面---》一打开页面就触发分页查询请求---》后端服务器接收请求处理并响应 3.接口设计: 接口地址: 请求方式:GET 接口入参:page=1&pageSize=10 接口响应:分页对象 R<Page<Category>> 需要records 和 total 4.数据模型:Category表 思路分析: controller: 在CategoryController定义一个分类分页查询的方法: 0.添加分页拦截器【第一次做分页一定要添加】 1.获取前端的参数page=1&pageSize=10 2.创建分页对象传入page=1&pageSize=10 3.调用service的分页接口,将分页对象传递给分页接口 4.返回结果给前端 service: MP已经提供了分页接口 dao: MP已经提供了分页接口 分类删除: 需求分析: 1.前端页面:/backend/page/category/list.html 2.请求流程:员工登录之后进入到首页index.html---》进入到分类管理页面---》点击删除操作触发请求---》后端服务器接收请求处理并响应 3.接口设计: 接口地址:/category?ids=1611633960582836226 请求方式:DELETE 接口入参:ids=1611633960582836226 接口响应:R<String> 删除成功|失败 4.数据模型:Category表、Dish表、Setmeal表 代码准备: bean: Category、Dish、Setmeal dao: CategoryDao、DishDao、SetmealDao service: CategoryService|CategoryServiceImpl、DishService|DishServiceImpl、SetmealService|SetmealServiceImpl controller: CategoryController、DishController、SetmealController 思路分析: controller: 在CategoryController定义一个分类删除方法: 1.调用service删除方法 2.返回结果 service: 在CategoryService中定义一个删除方法 1.判断当前分类下是否存在菜品数据 1.1 构造查询条件,根据分类id查询菜品表 1.2 如果存在数据,就直接返回删除失败 2.判断当前分类下是否存在套餐数据 2.1 构造查询条件,根据分类id查询套餐表 2.2 如果存在数据,就直接返回删除失败 3.调用父类的删除方法,Mp已经内置了删除方法 dao: MP已经提供了删除接口 分类修改: 需求分析: 1.前端页面:/backend/page/category/list.html 2.请求流程:员工登录之后进入到首页index.html---》进入到分类管理页面---》点击修改按钮---》修改分类名称和排序----》点击确定触发请求---》后端服务器接收请求处理并响应 3.接口设计: 接口地址:/category 请求方式:PUT 接口入参:{id: "1397844263642378242", name: "湘菜", sort: "2"} 封装到Category对象中 接口响应:R<String> 修改成功|失败 4.数据模型:Category表 实现思路: controller: 在CategoryController定义一个分类更新方法: 1.在更新之前做一下用户名判断,根据分类名称查询数据库,并且排除本身的数据【根据id排除】 2.调用service更新方法 3.返回结果 service: MP已经提供了更新接口 dao: MP已经提供了更新接口 day03: 文件上传下载: 文件上传:指的是将本地计算机上的文件传输到远程服务器的过程 文件下载:指的是将远程服务器上的文件以流的方式写给浏览器的过程或者将其下载到本地计算机的过程。 文件上传: 需求分析: 前端:用户要可以在浏览器页面上选择要上传的文件,携带要上传的文件发送请求到服务器 要求: 1.设置表单提交方式为post method="post" 2.设置表单类型为混合表单 可以有普通表单项和文件上传表单项 enctype="multipart/form-data" 3.在表单中提供文件上传选择框 后端:将用户上传的文件保存到服务器的指定位置 要求: 1.在controller里面处理文件上传的方法中定义一个MultipartFile类型参数 2.方法形参变量名要和文件上传表单name属性值保持一致 接口设计: 请求地址:/common/upload 请求方式:post 请求参数:file MultipartFile类型 响应数据:R<String> 上传成功的文件名称 代码实现: 前端:已完成 el-upload标签:文件上传组件 属性: 重要属性: action:文件上传表单提交地址 eg:/common/upload name:上传的文件字段名 默认值为file on-success:文件上传成功时绑定的事件函数 eg:handleAvatarSuccess 表示文件上传调用该函数执行 handleAvatarSuccess (response, file, fileList) { this.imageUrl = `/common/download?name=${response.data}` } 1.文件上传成功后,为imageUrl赋值 给了一个网络地址 表示文件上传成功之后下载到本地进行预览显示 2.文件上传成功后 服务器响应的数据文件名称 before-upload:文件上传之前绑定的事件函数 eg:beforeUpload 表示在文件上传之间进行检查校验 了解属性: class:设置类样式 show-file-list:设置是否显示文件上传列表 false:不显示 ref:设置当前表单的引用 可以看作是给form表单起个名称 方法后面使用时找到它 数据模型: imageUrl:上传成功的图片路径 后端: controller: 新建一个CommonController类,根据接口设计新增一个upload方法,方法内的逻辑: //上传的文件是一个临时文件,需要指定保存地址,否则本次请求结束后该文件被删除 //1.设置文件上传的路径 //2.保存上传文件 //3.返回服务器上传的文件名称 service: 不需要 dao: 不需要 代码优化: 优化1:如果不同的用户上传的相同名称的文件,会导致后上传覆盖前面上传的,因此对于用户上传到服务器的文件需要进行重命名,防止被覆盖 重命名后的文件名称应该是唯一的,如何保证文件名是唯一的:使用UUID 完成文件名称:filename=uuid+后缀名; 优化2:文件上传服务器保存位置是硬编码,不方便修改,可以将其放在配置文件application.yml中进行设置 注意:文件上传测试 需要先登录后台系统 文件下载: 需求分析: 图片要通过浏览器下载进行一个回显 本质:服务端将文件以流的形式写回浏览器的过程。 接口设计: 接口地址:/common/download?name=dc39892f-c9a9-46d7-8e0e-31c4246aaa11.jpg 请求方式:GET 接口入参:name=xxx.jpg 图片名称 接口响应:void 实现思路: 前端:已完成 后端: controller: 在CommonController中定义一个文件下载的方法: 1.创建一个输入流对象 FileInputStream 2.通过HttpServletResponse去获取输出流 3.数据读写 4.关闭流 service: 不涉及 dao: 不涉及 菜品模块: 新增菜品: 需求分析: 前端页面:/backend/page/food/add.html 请求流程:登录进入后台管理页面---》进入菜品管理页面---》点击新建菜品---》立即触发请求【http://localhost:8080/category/list?type=1】 --》输入菜品信息---》上传菜品图片【文件上传|下载请求】---》点击保存发送新增菜品请求【】---》后端进行处理并响应 请求梳理: 1.根据类型查询分类列表 【待实现】 【http://localhost:8080/category/list?type=1 + GET】 2.文件上传|下载请求 【已完成】 【http://localhost:8080/common/upload】 【http://localhost:8080/common/download?name=98690387-b99d-479a-a9f2-b1cfb420e3d9.jpg】 3.新增菜品请求 【待实现】 【http://localhost:8080/dish + POST】 接口设计: 1.根据类型查询分类列表 接口地址:/category/list 请求方式:GET 接口入参:type=1 接口响应:R<List<Category>> 2.新增菜品请求 接口地址:/dish 请求方式:POST 接口入参:包含菜品基本信息+口味列表数据 自定义一个对象DishDto(包含菜品基本信息+口味信息)来封装这个参数 接口响应:R<String> 新增成功|新增失败 数据模型:category表、dish菜品表、dish_flavor菜品口味表 category : dish = 1 对 多 dish : dish_flavor = 1 对 多 代码准备: bean: Dish\DishFlavor dao: DishFlavorDao service: DishFlavorService|DishFlavorServiceImpl controller: DishController 实现思路: 1.根据类型查询分类列表 前端:已完成 后端: controller: 在CategoryController中定义一个查询分类列表方法: //1.设置查询条件 //2.调用service的查询列表方法 //3.返回结果 service: Mp已提供 dao: Mp已提供 2.新增菜品接口: 前端:已完成 后端: controller: DishController中定义一个新增菜品方法: 1.调用service新增方法 2.返回结果 service: DishService中定义一个新增菜品方法(新增菜品信息+口味): 1.调用自身的新增方法,保存菜品的基本信息到dish表中 2.调用dishFlavorService的接口,保存菜品口味信息到dish_flavor表中 2.1 口味信息需要关联dish_id dao: Mp提供 菜品分页查询: 需求分析: 前端页面:/backend/page/food/list.html 请求流程:登录进入后台管理页面---》进入菜品管理页面---》立即触发分页查询请求---》后端处理请求并响应 接口设计: 接口地址:/dish/page?page=1&pageSize=10&name=%E8%8F%9C%E5%93%81 请求方式:GET 接口入参:page=1&pageSize=10 name(可选参数) 接口响应:分页对象 R<Page<List<Dish>>> 需要records 和 total 数据模型:Dish表 思路分析: controller: 在DishController定义一个菜品分页查询的方法: 0.添加分页拦截器【第一次做分页一定要添加】 1.创建分页对象传入page=1&pageSize=10 2.构造查询条件 name 3.调用service的分页接口,将分页对象以及查询对象传递给分页接口 4.返回结果给前端 service: MP已经提供了分页接口 dao: MP已经提供了分页接口 问题分析: 1.图片没有展示:D:\img\00874a5e-0df2-446b-8f69-a30eb7d88ee8.png (系统找不到指定的文件。) 原因:图片做下载,设置的路径是D:\img\,然后这个路径下面没有图片资源 解决:将资料中的图片资源全部拷贝到D:\img\即可 2.菜品分类没有展示: 原因:Dish对象没有菜品分类名称的这个属性 解决:自定义一个dto对象,封装dish菜品基本信息以及分类名称 直接放回Page<DishDto> 实现思路: 1.new Page<DishDto>对象 2.将Page<Dish>中的所有属性拷贝给Page<DishDto>,排除records属性 3.需要设置records属性【List<DishDto>】到Page<DishDto> 4.List<DishDto>数据的封装: 4.1 循环遍历List<Dish> 4.2 将dish对象拷贝到 DishDto 4.3 查询分类,根据分类id去查,得到分类对象,设置分类名称到dishDto中 4.4 将dish对象添加到List<DishDto> 5.返回Page<DishDto> 菜品修改: 需求分析: 前端页面:/backend/page/food/add.html?id=1397849739276890114 请求流程:登录进入后台管理页面---》进入菜品管理页面---》立即触发根据类型查询分类列表 根据id查询菜品相关信息包括口味信息---》修改菜品相关信息---》点击保存发送修改菜品请求【】 ---》后端处理请求并响应 请求梳理: 1.根据类型查询分类列表 【已完成】 【http://localhost:8080/category/list?type=1 + GET】 2.根据id查询菜品相关信息包括口味信息 【待实现】 【http://localhost:8080/dish/1397849739276890114 + GET】 3.修改菜品请求 【待实现】 【http://localhost:8080/dish + POST】 接口设计: 1.根据id查询菜品相关信息包括口味信息 接口地址:/dish/{id} 请求方式:GET 接口入参:id 菜品id 接口响应:菜品信息以及口味信息 DishDto封装 2.修改菜品请求 接口地址:/dish 请求方式:PUT 接口入参:菜品信息以及口味信息 DishDto封装 接口响应:R<String> 修改成功|失败 数据模型:dish表、dish_flavor表 实现思路: 1.根据id查询菜品相关信息包括口味信息 前端:已完成 后端: controller: 在DishController定义查询方法: 1.调用service的查询方法 2.直接返回查询结果 service: 在DishService定义查询接口,实现类实现查询接口: 0.先创建出DishDto对象,用来封装返回数据 1.查询dish表,将菜品基本信息查询出来,封装到dishDto 2.查询dish_flavor,将口味信息列表查询出来,封装到dishDto 3.返回DishDto对象 dao: Mp提供 2.新增接口 前端:已完成 后端: controller: 在DishController定义修改的方法: //1.调用service的更新方法 //2.返回成功结果 service: 在DishService中定义一个修改方法: //优化: 1.根据菜品名称查询数据库dish表,校验菜品名称是否存在 1.1 构造查询条件,根据菜品名称去查 1.2 排除自身,根据菜品id 1.3 调用service统计方法,判断是否有数据 2.保存菜品信息数据到dish表 3.保存口味信息数据到dish_flavor,关联菜品id 4.返回成功结果 dao: mp提供 day04: 套餐模块: 新增套餐: 需求分析: 1.前端页面:/backend/page/combo/add.html 2.请求流程:登录到后台系统进入到套餐管理页面---》点击新建套餐 add.html---》立即触发三个请求【1.查询套餐分类列表;2.查询菜品分类列表; 3.根据菜品分类查询菜品列表】---》补充套餐基本信息以及添加菜品---》上传套餐图片【文件上传|下载】---》点击保存发送新增套餐请求--》后端响应 请求梳理: 2.1 查询分类列表,根据类型 【已实现】 【http://localhost:8080/category/list?type=2&page=1&pageSize=1000 + GET】 【http://localhost:8080/category/list?type=1 + GET】 2.2 根据菜品分类查询菜品列表 【待完成】 【http://localhost:8080/dish/list?categoryId=1397844263642378242 + GET】 2.3 文件上传|下载 【已实现】 【http://localhost:8080/common/upload】 【http://localhost:8080/common/download?name=170948cf-6835-4fef-a61a-4abc6bf42f02.jpg】 2.4 新增套餐请求 【待实现】 【http://localhost:8080/setmeal + POST】 3.接口设计: 3.1 根据菜品分类或者菜品名称查询菜品列表 接口地址:/dish/list 请求方式:GET 接口入参:categoryId=1397844263642378242 | name=%E8%82%89 使用dish对象封装 接口响应:菜品数据 R<List<Dish>> 3.2 新增套餐请求 接口地址:/setmeal 请求方式:POST 接口入参:套餐基本信息+套餐菜品相关信息 需要使用Setmealdto来封装数据 接口响应:R<String> 新增成功|失败 4.数据模型:setmeal套餐表、setmeal_dish套餐菜品关系表、dish菜品表 setmeal:setmeal_dish = 1 对 多 代码准备: bean: Setmeal、SetmealDish dao: SetmealDao、SetmealDishDao service: SetmealService|SetmealServiceImpl、SetmealDishService|SetmealDishServiceImpl controller: SetmealController 实现思路: 1 根据菜品分类查询菜品列表 前端:已完成 后端: controller: 在DishController中定义一个查询菜品列表的方法: 1.创建查询对象 2.设置查询条件,根据菜品分类id查询或者根据菜品名称查询 3.调用service的查询方法list 4.返回结果给前端 service:MP已提供 dao:MP已提供 2 新增套餐请求 前端:已完成 后端: controller: 在SetmealController中定义一个新增套餐方法: 1.调用service的新增套餐方法 2.返回结果 service: 在SetmealService中定义一个新增套餐方法: 0.开启事务(涉及到多张表的新增或修改) 1.校验数据库中是否存在该套餐名称 2.保存套餐数据到setmeal套餐表 3.保存套餐菜品数据到setmeal_dish套餐菜品关系表 3.1 关联套餐id dao:MP提供 套餐分页查询: 需求分析: 1.前端页面:/backend/page/combo/list.html 2.请求流程:登录进入到后台系统---》点击套餐管理---》进入到list.html立即触发分页查询请求----》后端响应 3.接口设计: 接口地址:/setmeal/page?page=1&pageSize=10&name=aaa 请求方式:GET 接口入参:page=1&pageSize=10 name(可选参数) 接口响应:R<Page<SetmealDto>> records属性:存储数据列表List<SetmealDto> SetmealDto封装了分类名称以及套餐所有属性 4.数据模型:Setmeal套餐表 实现思路: 前端:已完成 后端: controller: 在SetmealController中定义一个分页查询方法: 1.调用service的分页查询 2.返回分页查询结果 service: 在SetmealService中定义一个分页查询方法: 1.new Page<SetmealDto>创建分页对象,records、total、size.... 2.封装 Page<SetmealDto>数据: 2.1 构造分页对象 Page<Setmeal>(page, pageSize) 2.2 构造查询对象,可以根据套餐名称进行分页查询 2.3 调用自身的page方法,传入分页对象以及查询对象,最终得到Page<Setmeal>对象数据,里面records(List<Setmeal>)、total、size.... 2.4 Page<Setmeal>所有属性拷贝到Page<SetmealDto>,排除records属性 2.5 封装Page<SetmealDto>的records属性:List<SetmealDto> a.循环遍历List<Setmeal> b.构造SetmealDto对象数据,设置setmeal属性 c.获取categoryName属性(根据分类id查询分类表)封装到SetmealDto d.将SetmealDto对象添加到List<SetmealDto> 2.6 设置Page<SetmealDto>对象的records属性:List<SetmealDto> 3.返回Page<SetmealDto> dao: MP提供 删除套餐: 需求分析: 1.前端页面:/backend/page/combo/list.html 2.请求流程:登录进入到后台系统---》点击套餐管理---》点击删除操作---》发送删除请求---》后端响应 3.接口设计: 接口地址:/setmeal 请求方式:DELETE 接口入参:ids=1415580119015145474,1612639672565960706 接口响应:R<String> 删除成功|失败 4.数据模型:Setmeal套餐表、Setmeal_dish套餐菜品表 实现思路: 前端:已完成 后端: controller: 在SetmealController中定义一个删除方法: 1.调用service的删除方法 2.返回结果 service: 在SetmealService中定义一个删除方法: 0.开启事务 1.删除前检查套餐的状态,如果是售卖中的不允许删除 2.先删除套餐表里的数据setmeal 3.再删除套餐菜品表的数据(根据setmel_id) dao: mp提供 移动端模块: 手机验证码登录: 需求分析: 前端页面:/front/page/login.html 请求流程:输入手机号---》点击获取验证码【发送请求】---》服务器响应---》输入验证码--》点击登录【发送登录请求】---服务器接收请求响应 接口设计: 1.获取验证码 【前端也要完善】 接口地址:/user/sendMsg 请求方式:POST 接口入参:{"phone":"131000011111"} 接口响应:R<String> 响应验证给前端 2.登录请求 【前端也要完善】 接口地址:/user/login 请求方式:POST 接口入参:{"phone":"131000011111","code":"1234"} Map对象来封装 接口响应:R<String> 登录成功|失败 数据模型:user表 代码准备: bean: User dao: UserDao service: UserService\UserServiceImpl controller: UserController 实现思路: 前端: login.html---》获取验证码getCode() //优化获取验证码 const res = await sendMsg({phone: this.form.phone}) if (res.code === 1) { this.$message.success(res.data) } else { this.$notify({type: 'warning', message: res.msg}); } 封装发送获取验证码的接口 function sendMsgApi(data) { return $axios({ 'url': '/user/sendMsg', 'method': 'post', data }) } 登录请求:完善请求参数,补充验证码 loginApi({phone:this.form.phone, code:this.form.code}) 后端: 1.获取验证码 controller: 在UserController中定义一个获取验证码方法: 1.获取前端传递的手机号 2.调用生成验证码工具类来生成验证码code, 缓存验证码 用session缓存 //用redis缓存数据 3.调用阿里云API给对应的手机号发送短信 4.返回结果R<String> 验证码返回给前端 service: 不涉及 dao: 不涉及 2.登录请求 controller: 在UserController中定义一个登录方法: 1.获取前端传递的手机号以及验证码 2.校验验证码:从session中获取验证码与前端传递过来的验证码作比较 3.如果不一致,直接返回错误信息 4.判断当前登录的手机号是否存在数据库,如果不存在要去初始化该用户数据 5.返回登录成功,将userId缓存到session中(为了用户登录校验) service:mp提供 dao:mp提供 day05: 移动端: 菜品展示: 需求分析: 前端页面:/front/index.html 请求流程:用户登录进入移动端首页后---》立即触发请求【1.查询分类列表数据;2.查询购物车列表数据;3.查询菜品列表|套餐列表】---》后端响应 请求梳理: 1.查询分类列表数据: 【待优化】 【http://localhost:8080/category/list + GET】 2.查询购物车列表数据 【待完成】 【http://localhost:8080/shoppingCart/list + GET】 3.1查询菜品列表 (前面1和2两个请求全部成功,才会触发,根据分类的第一条数据类型来判断查菜品查套餐) 【http://localhost:8080/dish/list?categoryId=1397844263642378242&status=1 + GET 3.2查询套餐列表 (前面1和2两个请求全部成功,才会触发,根据分类的第一条数据类型来判断查菜品查套餐) 【http://localhost:8080/setmeal/list?categoryId=1413386191767674881&status=1 + GET】 接口设计: 1、查询菜品列表 【待优化】 接口地址:/dish/list 请求方式:GET 接口入参:categoryId=1397844263642378242&status=1 封装dish对象 接口响应:R<List<DishDto>> 菜品列表数据+口味信息 2、查询套餐列表 【待实现】 接口地址:/setmeal/list 请求方式:GETa 接口入参:categoryId=1397844263642378242&sttus=1 封装Setmeal对象 接口响应:R<List<Setmeal>> 套餐列表数据 数据模型:category表、dish菜品表、dish_flavor口味表、setmeal套餐表 代码准备:无 实现思路: 1.查询分类列表数据 【优化】 前端:已完成 后端: 优化CategoryController中的list方法即可: 1.将查询条件做一个条件判断 wrapper.eq(Category::getType, type); 2.如果没有传值,就不设置该条件 wrapper.eq(type!=null, Category::getType, type); 2.查询购物车列表数据 【伪代码实现】 前端: 1.在front下创建一个cartData.json 2.修改cartListApi中的'url': '/shoppingCart/list',----> 'url': '/front/cartData.json' 后端:待实现 3. 查询菜品列表 【优化】 前端:已完成 后端: controller: 在DishController重新定义一个查询列表的方法: 1.调用service的查询列表方法 2.返回结果 service: 在DishService定义一个查询列表的方法: 1.设置查询条件:分类id、菜品名称、菜品状态 2.调用父接口的查询方法,得到的List<Dish> 3.封装List<DishDto>数据 4.循环遍历List<Dish> 5.根据dish对象去封装DishDto 6.根据dishId去查口味表,将口味信息封装到DishDto 7.将dishDto添加到List<DishDto> 8.返回List<DishDto>给controller dao: mp提供 4. 查询套餐列表 【待实现】 前端:已完成 后端: controller: 在SetmealController中定义一个查询列表的方法: 1.根据分类id以及套餐状态进行查询,需要构造查询条件 2.调用service的查询列表方法 3.返回结果 service: mp提供 dao: mp提供 购物车: 需求分析: 前端页面:/front/index.html 请求流程:用户登录进入移动端首页后---》点击添加菜品或者添加套餐到购物车---》触发添加购物车请求---》后端响应 请求梳理: 1.添加购物车 【待实现】 【http://localhost:8080/shoppingCart/add + POST】 2.查询购物车 【待实现】 【http://localhost:8080/shoppingCart/list + GET】 3.清空购物车 【待实现】 【http://localhost:8080/shoppingCart/clean + DELETE】 接口设计: 1.添加购物车 接口路径:/shoppingCart/add 请求方式:POST 接口入参: 添加菜品:{amount: 128, dishFlavor: "微辣", dishId: "1397860242057375745", name: "脆皮烧鹅",…} 添加套餐:{amount: 40, setmealId: "1415580119015145474", name: "儿童套餐A计划",…} 用shoppingCart对象来封装 接口响应:R<ShoppingCart> 购物车数据 2.查询购物车 接口路径:/shoppingCart/list 请求方式:GET 接口入参:无 注意:根据userId来查询当前登录用户的购物车 接口响应:R<List<ShoppingCart>> 3.清空购物车 接口路径:/shoppingCart/clean 请求方式:DELETE 接口入参:无 注意:根据userId来清空当前登录用户的购物车 接口响应:R<String> 清空购物车成功|失败 数据模型:shopping_cart购物车表 代码准备: bean: ShoppingCart dao: ShoppingCartDao service: ShoppingCartService|ShoppingCartServiceImpl controller: ShoppingCartController 实现思路: 1.添加购物车 前端:已完成 后端: controller: 在ShoppingCartController定义一个添加购物车的方法: 1. 判断当前购物车中是否存在该商品 2. 如果存在该商品,直接number数量+1 3. 如果不存在该商品,需要补齐一些字段:user_id、number、crate_time 4. 调用service保存购物车数据 5. 返回结果 service: mp提供 dao: mp提供 2.查询购物车 前端:优化 main.js中的查询接口地址'url': '/front/cartData.json',修改回'url': '/shoppingCart/list' 后端: controller: 在ShoppingCartController中定义一个查询购物车方法(根据当前用户id查询购物车): 1.获取当前登录用户的id 2.根据当前用户id查询购物车 3.返回结果 service: mp提供 dao: mp提供 3.清空购物车 前端:已完成 后端: controller: 在ShoppingCartController中定义一个清空购物车方法(根据当前用户id清空购物车): 1.获取当前登录用户的id 2.根据当前用户id清空购物车,调用service删除方法 3.返回结果 service: mp提供 dao: mp提供 下单: 需求分析: 前端页面:/front/index.html + /front/page/add-order.html 请求流程:用户登录进入移动端首页后---》点击去结算---》立即触发请求【1.查询默认地址;2.查询购物车列表】---》徐备注信息---》 点击去支付----》触发请求【下单操作】---》后端响应 请求梳理: 1.查询默认地址; 【已完成】 【http://localhost:8080/addressBook/default + GET】 2.查询购物车列表 【已完成】 【http://localhost:8080/shoppingCart/list + GET】 3.下单操作 【待实现】 【http://localhost:8080/order/submit + POST】 接口设计: 下单操作: 接口地址:/order/submit 请求方式:POST 接口入参:{remark: "加量!!!", payMethod: 1, addressBookId: "1613001936865390594"} 用Orders对象封装参数 接口响应:R<String> 提交成功|失败 数据模型:orders订单、order_detail订单详情表 = 1对多 代码准备: bean: Orders、OrderDetail dao: OrdersDao、OrderDetailDao service: OrdersService\OredersServiceImpl、OrderDetailService\OrderDetailServiceImpl controller: OrdersController 实现思路: 前端:已完成 后端: controller: 在OrdersController中定义下单方法: 1.调用service的下单方法 2.返回结果 service: 在OrdersService中定义下单方法: 0.开启事务 1.保存订单明细数据到order_detail表中 2.构造orderDetail订单明细数据: 2.1 将购物车数据信息直接拷贝到订单明细对象中 2.2 设置订单id 2.3 订单明细数据保存到order_detail表中 3.保存订单信息数据到orders表中 4.需要补齐一些字段 5.保存订单数据到orders表中 6.清空购物车 dao: mp提供
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。