代码拉取完成,页面将自动刷新
瑞吉外卖项目环境搭建: 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/"); } } 项目功能开发 【分析模板】 需求分析: 1.前端页面: 2.请求流程: 3.接口设计: 接口路径: 请求方式: 接口入参: 接口响应: 4.数据模型: 代码准备: 前端: 后端: bean: dao: service: controller: 思路分析: 前端: 后端: controller: service: dao: day01 员工模块: 后台员工登录 需求分析: 1.前端页面:/backend/page/login/login.html 2.请求流程:进入到登录页面---》输入用户名和密码---》点击登录按钮---》发送请求到后端服务器---》后端接收请求并响应 3.接口设计: 接口路径:/employee/login 请求方式:POST 接口入参:{"username":"admin","password":"123456"} json格式数据 接口响应:员工信息Employee对象 R<Employee> 4.数据模型: Employee员工表 代码准备: 前端:页面小王表姐已完成 后端: bean: Employee dao: EmployeeDao service: EmployeeService接口、EmployeeServiceImpl实现类 controller: EmployeeController common: R 统一返回数据格式 思路分析: 前端: 已完成 后端: controller: 在EmployeeController在定义一个登录的方法 1、将页面提交的密码password进行md5加密处理 2、根据页面提交的用户名username查询数据库 3、如果没有查询到则返回登录失败结果 4、密码比对,如果不一致则返回登录失败结果 5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果 6、登录成功,将员工id存入Session并返回登录成功结果 service: mp提供 dao: mp提供 后台员工登录 需求分析: 1.前端页面:/backend/index.html 2.请求流程:员工登录之后---》进入到后台首页---》点击退出按钮---》发送退出请求---》后端接收请求并响应 3.接口设计: 接口路径:/employee/logout 请求方式:POST 接口入参:无 接口响应:R<String> 退出成功|失败 4.数据模型: Employee员工表 思路分析: 前端: 已完成 后端: controller: 在EmployeeController中定义一个退出的方法: 1.清理session中的id 2.返回结果 service: 不涉及 dao: 不涉及 完善登录功能: 问题分析: 前面我们已经完成了后台系统的员工登录功能开发,但是还存在一个问题:用户如果不登录,直接访问系统首页面,照样可以正常访问。 这种设计并不合理,我们希望看到的效果应该是,只有登录成功后才可以访问系统中的页面,如果没有登录则跳转到登录页面。 那么,具体应该怎么实现呢? 答案就是使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面。 解决方案: 使用过滤器 思路分析: 1、创建自定义过滤器LoginCheckFilter 2、在启动类上加入注解@ServletComponentScan 作用:扫描@WebFilter注解,将其修饰的过滤器交由spring容器管理 3、完善过滤器的处理逻辑: 1、获取本次请求的URI 2、判断本次请求是否需要处理 3、如果不需要处理,则直接放行 4、判断登录状态,如果已登录,则直接放行 5、如果未登录则返回未登录结果 新增员工: 需求分析: 1.前端页面:/backend/page/member/add.html 2.请求流程:登录成功后进入到后台首页,默认进入到员工管理页面---》点击添加员工按钮---》进入到添加员工页面---》补全员工信息,点击保存 ---》发送新增员工请求---》后端接收请求并响应 3.接口设计: 接口路径:/employee 请求方式:POST 接口入参:{"name":"aaa","phone":"13100001111","sex":"1","idNumber":"101010199910101010","username":"aaa"} 封装到Employee对象中 接口响应:添加成功|失败 R<String> 4.数据模型: 员工表 Employee 思路分析: 前端:已完成 后端: controller: 在EmployeeController中定义一个新增方法: 1.补齐字段 2.调用service新增方法 3.返回结果 service: mp已提供 dao: mp已提供 存在的问题:新增相同的用户名,会报错,如下: Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'zhangsan' for key 'idx_username' 解决方案: 新增员工之前,判断该用户名是否已经存在数据库中 功能开发day02 员工分页查询: 需求分析: 1.前端页面:/backend/page/member/list.html 2.请求流程:后台系统登录---》进入到员工管理页面---》一进入到页面就会触发分页查询请求---》后端接收请求并响应 3.接口设计: 接口路径:/employee/page 请求方式:GET 接口入参:page=1&pageSize=10&name=zhangsan 接口响应:分页对象 R<Page<Employee>> records和total 4.数据模型: 员工表Employee 思路分析: 前端:已完成 后端: controller: 在EmployeeController中定义一个分页查询方法:(用到mp的分页) 0.添加分页拦截器 1.设置分页对象 Page对象 2.设置查询条件 3.调用service的分页查询方法 4.返回结果 service: mp已提供 dao: mp已提供 员工启用|禁用: 需求分析: 前端页面:/backend/page/member/list.html 请求流程:管理员登录到后台系统---》进入到员工管理页面--》点击启用|禁用按钮---》发送请求到后端---》后端接收请求并响应 接口设计: 接口路径:/employee 请求方式:PUT 接口入参:{"id":1627559129184710700,"status":0} json格式数据,封装到Employee对象中 接口响应:R<String> 更新成功|失败 数据模型: 员工表Employee 思路分析: 前端:已完成 后端: controller: 在EmployeeController中定义一个更新方法: 1.补齐更新时间和更新人 2.调用service更新方法根据id更新 3.返回结果 service: mp已提供 dao: mp已提供 问题分析: 测试过程中没有报错,但是功能并没有实现,查看数据库中的数据也没有变化。 通过观察控制台输出的SQL发现页面传递过来的员工id的值和数据库中的id值不一致,这是怎么回事呢? 原因: 前面我们已经发现了问题的原因,即js对long型数据进行处理时丢失精度,导致提交的id和数据库中的id不一致。 解决: 我们可以在服务端给页面响应json数据时进行处理,将long型数据统一转为String字符串 具体实现步骤: 1)提供对象转换器基于Jackson进行Java对象到json数据的转换(资料中已经提供,直接复制到项目中使用)JacksonObjectMapper, 2)在WebMvcConfig配置类中扩展Spring mvc的消息转换器,在此消息转换器中使用提供的对象转换器进行Java对象到json数据的转换 员工编辑: 需求分析: 前端页面:/backend/page/member/add.html 请求流程:管理员|员工登录进后台--》进入到员工管理页面---》点击编辑按钮---》进入到编辑页面---》立即触发请求【根据员工id查询员工信息】 ---》修改员工信息---》点击保存--》发送保存请求【更新】---》后端接收请求并响应 接口设计: 1.根据员工id查询员工信息 接口路径:/employee/{id} 请求方式:GET 接口入参:路径参数id 接口响应:员工对象信息 R<Employee> 2.更新员工信息: 接口路径:/employee 请求方式:PUT 接口入参:{id: "1627524327769354242", username: "zhangsan", name: "张三01",…} json格式数据,封装到Employee对象中 接口响应:R<String> 更新成功|失败 数据模型: 员工表Employee 思路分析: 1.根据员工id查询员工信息 前端:已完成 后端: controller: 在EmployeeController中定义一个查询方法 1.调用service的查询方法(根据id查询) 2.返回结果 service: mp提供 dao: mp提供 2.更新员工信息 ---需要优化: 在更新员工信息之前,先查询员工表,判断当前修改的用户名是否存在(根据前端传递的用户名查询,注意:要排除它自生数据) 分类管理模块: 公共字段自动填充: 问题分析: 前面我们已经完成了后台系统的员工管理功能开发,在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段, 在编辑员工时需要设置修改时间和修改人等字段。这些字段属于公共字段,也就是很多表中都有这些字段 能不能对于这些公共字段在某个地方统一处理,来简化开发呢? 解决方案:答案就是使用Mybatis Plus提供的公共字段自动填充功能。 Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。 实现步骤: 1、在实体类的属性上加入@TableField注解,指定自动填充的策略 2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口 方式一:使用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"} json格式 封装Category对象中 接口响应:R<String> 新增成功|失败 4.数据模型: 分类表Category 代码准备: 前端:已完成 后端: bean: Category dao: CategoryDao service: CategoryService 接口、CategoryServiceImpl 实现类 controller: CategoryController 思路分析: 前端:已完成 后端: controller: 在CategoryController中定义一个新增方法: 0.补齐字段【使用mp的字段自动填充功能,可以省略这一步】 1.查询数据库,判断当前分类名称是否已存在,如果已存在直接返回新增失败 2.不存在的话,直接调用service的save方法 3.返回结果 service: mp已提供 dao: mp已提供 分类分页查询: 需求分析: 1.前端页面:/backend/page/category/list.html 2.请求流程:员工登录后台系统--》进入到分类管理页面---》立即触发分页查询请求---》后端接收请求并响应 3.接口设计: 接口路径:/category/page 请求方式:GET 接口入参:page=1&pageSize=10 接口响应:分页对象 R<Page<Category>> records和total 4.数据模型: 分类表Category 思路分析: 前端:已完成 后端: controller: 在CategoryController中定义一个分页方法: 0.添加分页拦截器【在员工管理模式开发已添加,此处可省略】 1.设置分页对象 Page对象 2.设置查询条件,根据sort排序 3.调用service的分页查询方法 4.返回结果 service: mp已提供 dao: mp已提供 删除分类: 需求分析: 1.前端页面:/backend/page/category/list.html 2.请求流程:员工登录后台系统--》进入到分类管理页面---》点击删除按钮发送删除请求---》后端响应 3.接口设计: 接口路径:/category 请求方式:DELETE 接口入参:ids=1627879962746740737 接口响应:R<String> 成功|失败 4.数据模型: 分类表 category、菜品表 dish、套餐表 setmeal 关系:category:dish ---》1对多、category:setmeal ---》1对多 代码准备: bean: Category、Dish、Setmeal dao: CategoryDao、DishDao、SetmealDao service: CategoryService |CategoryServiceImpl、DishService |DishServiceImpl、SetmealService|SetmealServiceImpl controller: CategoryController 思路分析: 前端:已完成 后端: controller: 在CategoryController中定义一个删除方法: 1.调用service的删除方法 2.返回结果 service: 在CategoryService中定义一个删除方法: 1.查询菜品表(根据分类id查),如果存在菜品,则不能删除 2.查询套餐表(根据分类id查),存在套餐数据,则不能删除 3.没有关联的菜品或者套餐,则直接调用父接口的删除方法 dao: mp已提供 修改分类: 需求分析: 1.前端页面:/backend/page/category/list.html 2.请求流程:员工登录后台系统--》进入到分类管理页面---》点击修改---》弹出对话框---》修改分类名称和排序---》点击确定发送修改请求---》后端响应 3.接口设计: 接口路径:/category 请求方式:PUT 接口入参:{"id":"1627883883326308353","name":"菜品二","sort":"1"} json格式 封装到Category对象中 接口响应:R<String> 修改成功|失败 4.数据模型: Category 思路分析: 前端:已完成 后端: controller: 在CategoryController中定义一个修改方法: 1.查询数据表Category,判断是否存在当前分类名称(排除自身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中定义一个文件上传方法: //注意:上传的文件是一个临时的文件,如果不存储上传完成会立即被删除 //1.设置文件存储路径(包括文件名) //2.保存上传的文件 //3.返回结果(文件名称) service: 不涉及 dao: 不涉及 文件下载: 本质:服务器将文件以流的形式写回浏览器的过程 接口设计: 请求地址:/common/download?name=4124838f-24a7-41b3-945b-e09e15692f27.jpg 请求方式:GET 请求参数:name=4124838f-24a7-41b3-945b-e09e15692f27.jpg 响应数据:无 思路分析: 前端:已完成 后端: controller: 在CommonController中定义一个文件下载的方法: 1.创建一个文件输入流 2.通过HttpServletResponse 创建输出流 3.输入流数据读写 4.关闭流 server: 不涉及 dao: 不涉及 菜品管理模块: 新增菜品: 需求分析: 1.前端页面:/backend/page/food/add.html 2.请求流程:员工登录到后台系统---》进入到菜品管理页面---》点击新增菜品---》进入到菜品新增页面,立即触发请求【查询分类列表】---》 填写菜品基本信息【图片上传|下载】---》点击保存【触发保存请求】---》后端接受请求并响应 请求梳理: 2.1 查询分类列表 【待实现】 【http://localhost:8080/category/list?type=1 + GET】 2.2 图片上传|下载 【已完成】 【http://localhost:8080/common/upload + POST】 【http://localhost:8080/common/download?name=42f9bf43-6d93-4ef0-ae5d-40b856884832.jpg + GET】 2.3 保存菜品请求 【待实现】 【http://localhost:8080/dish + POST】 3.接口设计: 3.1 查询分类列表 接口路径:/category/list 请求方式:GET 接口入参:type=1 接口响应:R<List<Category>> 分类列表 3.2 保存菜品 接口路径:/dish 请求方式:POST 接口入参:{"name":"test","price":1200,"code":"","image":"9aba0861-277d-42"...} json格式 考虑封装到Dish实体类?? 入参包含口味信息,无法封装到Dish对象中,需要自定义一个实体类来封装 使用DishDto 接口响应:R<String> 新增成功|失败 4.数据模型: Category 分类表、Dish 菜品表、Dish_Flavor 菜品口味表 Category:Dish = 1 对 多 Dish : Dish_Flavor = 1 对 多 代码准备: 前端: 后端: bean: Category、Dish、DishFlavor dao: CategoryDao、DishDao、DishFlavorDao service: DishService\DishServiceImpl、DishFlavorService|DishFlavorServiceImpl controller: DishController 思路分析: 1. 查询分类列表 前端:已完成 后端: controller: 在CategoryController中定义一个查询列表的方法: 1.根据类型type查询,创建查询对象,设置查询条件 2.调用service的查询列表方法 3.返回结果 service: mp已提供 dao: mp已提供 2. 新增菜品 前端:已完成 后端: controller: 在DishController中定义新增菜品方法: 1.调用service的新增方法 2.返回结果 service: 在DishService中定义新增菜品方法: 0.开启事务(涉及到多张表的更新) 1.保存菜品基本信息到dish表 2.保存菜品口味信息到dish_flavor表中 2.1 关联菜品id dao: mp已提供 菜品分页查询: 需求分析: 1.前端页面:/backend/page/food/list.html 2.请求流程:登录到后台系统--》进入菜品管理页面--》立即触发分页查询请求---》后端响应 3.接口设计: 接口路径:/dish/page 请求方式:GET 接口入参:page=1&pageSize=10&name=%E9%B8%A1%E8%82%89 接口响应:R<Page<Dish>> 4.数据模型: Dish菜品表 思路分析: 前端:已完成 后端: controller: 在EmployeeController中定义一个分页查询方法:(用到mp的分页) 0.添加分页拦截器 1.设置分页对象 Page对象 2.设置查询条件 3.调用service的分页查询方法 4.返回结果 service: mp已提供 dao: mp已提供 存在的问题: 1.菜品图片未显示:.FileNotFoundException: D:\img\aaa\bbb\ded0a754-0494-4fda-9667-622c19868cca.jpg (系统找不到指定的文件。) 原因:文件上传下载的路径设置的是D:\img\aaa\bbb\,这个路径下图片资源并不存在 解决:将资料中的图片资源放到D:\img\aaa\bbb\下 2.菜品分类名称未展示: 原因:dish对象中并没有分类名称这个属性 解决:自定义一个dto实体类,来封装分类名称,直接使用DishDto,返回改成R<Page<DishDto>> 实现思路: 1.创建一个新的page对象Page<DishDto> 2.直接将Page<Dish>对象所有属性复制给Page<DishDto>,可以排除掉records这个属性 3.设置Page<DishDto>的records属性,构造List<DishDto>数据 3.1 循环遍历List<Dish>,将dish数据复制给dishDto 3.2 查询出category,将分类名称赋值给dishDto 3.3 将dishDto添加到List<DishDto> 4.设置Page<DishDto>的records属性 5.返回结果 修改菜品: 需求分析: 1.前端页面:/backend/page/food/add.html?id=1397849739276890114 2.请求流程:进入菜品管理页面---》点击修改按钮---》进入到修改页面---》立即触发请求【1.查询分类列表;2.查询菜品信息包含口味信息】---》 修改菜品信息---》点击保存---》发送【修改菜品的请求】---》后端响应 请求梳理: 2.1.查询分类列表 【已实现】 【http://localhost:8080/category/list?type=1 + GET】 2.2 查询菜品信息包含口味信息 【待完成】 【http://localhost:8080/dish/1397849739276890114 + GET】 2.3 修改菜品的请求 【待完成】 【http://localhost:8080/dish + PUT】 3.接口设计: 3.1查询菜品信息包含口味信息 接口路径:/dish/{id} 请求方式:GET 接口入参:路径参数 id 接口响应:R<DishDto> 3.2 修改菜品 接口路径:/dish 请求方式:PUT 接口入参:{"id":"1397849739276890114","name":"辣子鸡","categoryId":"1397844263642378242"...} json格式 封装到DishDto 接口响应:R<String> 修改成功|失败 4.数据模型: dish、dish_flavor 思路分析: 1. 查询菜品信息包含口味信息 前端:已完成 后端: controller: 在DishController中定义一个查询方法: 1.调用service的查询方法 2.返回结果 service: 在DishService中定义一个查询方法 1.根据菜品id查询菜品表,得到菜品的基本信息封装到dishDto 2.根据菜品id查询菜品口味信息表,得到口味信息列表,封装到dishDto 3.返回dishDto dao: mp已提供 2. 修改菜品 前端:已完成 后端: controller: 在DishController中定义一个修改方法: 1.调用service的修改方法 2.返回结果 service: 在DishService中定义一个修改方法: 0.开启事务(涉及多表更新操作) 1.调用父类的修改方法,修改菜品信息dish表 2.修改口味信息(修改、删除、新增),简单一点直接先清空口味信息 3.调用dishFlavorService保存口味信息(关联菜品id) dao: mp提供 day04: 套餐模块: 新增套餐 需求分析: 1.前端页面:/backend/page/combo/add.html 2.请求流程:登录进入后台管理系统---》点击套餐管理页面---》点击新建套餐---》立即触发三个请求【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】 【http://localhost:8080/dish/list?name=%E9%B8%A1%E8%82%89 + GET】 2.3 文件上传|下载请求 【已完成】 【http://localhost:8080/common/upload + POST】 【http://localhost:8080/common/download?name=af8a13c6-3a74-424c-b434-5c2e9ad72339.png + GET】 2.4 新增套餐请求 【待完成】 【http://localhost:8080/setmeal + POST】 3.接口设计: 3.1 查询菜品列表 接口路径:/dish/list 请求方式:GET 接口入参:categoryId=1397844263642378242 或者 name=%E9%B8%A1%E8%82%89 接口响应:R<List<Dish>> 3.2 新增套餐请求 接口路径:/setmeal 请求方式:POST 接口入参:{"name":"套餐一","categoryId":"1413342269393674242","price":12800..} json格式数据:包含套餐基本信息 以及套餐菜品信息 需要封装到自定义的dto--->SetmealDto 接口响应:R<String> 新增成功|新增失败 4.数据模型: 菜品表 dish 套餐表setmeal 套餐菜品表 setmeal_dish setmeal : setmeal_dish = 1 对 多 代码准备: 前端:已完成 后端: bean: Setmeal SetmelDish dao: SetmealDao、SetmelDishDao service: SetmealService|SetmealServiceImpl、SetmelDishService|SetmelDishServiceImpl controller: SetmealController 思路分析: 1.查询菜品列表 前端:已完成 后端: controller: 在DishController中定义一个查询列表方法: 1.创建查询对象 2.设置查询条件 3.调用service查询方法 4.返回结果 service: mp已提供 dao: mp已提供 2.新增套餐 前端:已完成 后端: controller: 在SetmealController中定义一个新增方法: 1.调用service的新增方法 2.返回结果 service: 在SetmealService中定义一个新增方法: 0.开启事务 1.直接调用继承父类的新增方法,保存套餐基本信息到setmeal表中 2.循环遍历套餐菜品列表数据,关联套餐id 3.批量保存套餐菜品列表数据到setmeal_dish表中 dao: mp已提供 套餐分页查询: 需求分析: 1.前端页面:/backend/page/combo/list.html 2.请求流程:登录进入到后台系统---》点击套餐管理---》进入到套餐页面立即触发分页查询请求----》后端响应 3.接口设计: 接口路径:/setmeal/page 请求方式:GET 接口入参:page=1&pageSize=10&name=%E5%95%86%E5%8A%A1 接口响应:R<Page<Setmeal>> 优化---》R<Page<SetmealDto>> 4.数据模型: Setmeal套餐表 思路分析: 前端:已完成 后端: controller: 在SetmealController定义一个分页方法 1.调用service的分页查询 2.返回结果 service: 在SetmealService定义一个分页方法 1.创建分页对象,Page(page, pageSize) 2.创建查询对象,设置查询条件 3.直接调用分页方法 4.返回分页结果 dao: mp已提供 优化:展示套餐图片 service: 在SetmealService定义一个分页方法 1.创建分页对象Page<Setmeal>,Page(page, pageSize) 2.创建查询对象,设置查询条件 3.直接调用分页方法 //a.创建Page<SetmealDto> //b.将Page<Setmeal>对象的所有属性拷贝给Page<SetmealDto>,排除records属性 //c.构造Page<SetmealDto>的records属性,records里面存的数据List<SetmealDto> //d.SetmealDto需要封装Setmeal的所有属性以及categoryName属性 //e.根据List<Setmeal>循环遍历,将setmeal所有属性值拷贝给SetmealDto //f.查询category分类表(根据分类id),获取分类名称封装到SetmealDto中 //g.添加到List<SetmealDto> //h.设置Page<SetmealDto>的records属性 4.返回分页结果 Page<SetmealDto> 删除套餐: 需求分析: 1.前端页面:/backend/page/combo/list.html 2.请求流程:登录进入后台系统--》点击套餐管理---》点击删除按钮(删除单条数据)|勾选复选框,选中多条数据,点击批量删除--》 触发删除请求---》后端响应 3.接口设计: 接口路径:/setmeal 请求方式:DELETE 接口入参:ids=1628941974520147970,1628928768582053889 接口响应:R<String> 删除成功|失败 4.数据模型: 套餐表:setmeal 套餐菜品表:setmeal_dish 思路分析: 前端:已完成 后端: controller: 在SetmealController中定义一个删除方法: 1.调用service层的删除 2.返回结果 service: 在SetmealService中定义一个删除方法: 0.开启事务 1.删除之前,需要判断这个套餐的状态是否已停售,如果是起售状态不能删除 2.直接删除setmeal基本信息数据 3.根据套餐id,删除套餐菜品数据setmeal_dish dao: mp已提供 移动端: 手机验证码登录: 需求分析: 1.前端页面:/front/page/login.html 2.请求流程:进入到移动端登录页面---》输入手机号---》点击获取验证码【】---》后端响应发送验证码到手机上---》用户复制验证码填写---》 点击登录【http://localhost:8080/user/login】--》后端响应 3.接口设计: 3.1 获取验证码 接口路径:/user/sendMsg 请求方式:POST 接口入参:{"phone":"17700001111"} json格式 封装到user对象中 接口响应:R<String> 3.2 登录请求 接口路径:/user/login 请求方式:POST 接口入参:{"phone":"17700001111","code":"1234"} json格式 封装到Map对象中 接口响应:R<String> 登录成功|失败 4.数据模型: User用户表 代码准备: 后端: bean: User dao: UserDao service: UserService controller: UserController 思路分析: 1、获取验证码 前端: login.html //优化前端获取验证码请求 const res = await sendMsg({phone:this.form.phone}) if(res.code === 1){ this.$message.success("获取验证码成功"); }else{ this.$message.error("获取验证码成功"); } login.js中补充方法: function sendMsg(data) { return $axios({ 'url': '/user/sendMsg', 'method': 'post', data }) } 后端: controller: 在UserController中定义一个获取验证码的方法: 1.获取前端传递手机号 2.生成验证码(调用util工具类) 3.发送验证码到指定的手机号 4.保存验证码,用HttpSession //用redis缓存 5.返回结果 service: mp已提供 dao: mp已提供 2. 登录请求 前端: login.html 登录请求参数补充验证码: const res = await loginApi({phone:this.form.phone, code:this.form.code}) 后端: controller: 在UserController中定义一个登录的方法 1.获取前端传递过来的手机号和验证码 2.校验验证码是否正确,如果不一致就返回错误信息 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和2两个请求全部成功,才会触发第三个请求】 【待完成菜品列表,待实现套餐列表】 【http://localhost:8080/dish/list?categoryId=1397844263642378242&status=1 + GET】 【http://localhost:8080/setmeal/list?categoryId=1413386191767674881&status=1 + GET】 接口设计: 1.获取分类对应的菜品|套餐 接口路径:/dish/list 请求方式:GET 接口入参:categoryId=1397844263642378242&status=1 为了兼容后台的查询方法 参数加上 name=xxx 接口响应:R<List<DishDto>> 菜品信息以及口味信息 2.获取分类对应的套餐 接口路径:/setmeal/list 请求方式:GET 接口入参:categoryId=1413386191767674881&status=1 接口响应:R<List<Setmeal>> 数据模型: dish菜品表、dish_flavor 口味表、 setmeal套餐表 实现思路: 1.查询购物车列表 前端:【伪代码实现】 //获取购物车内商品的集合 function cartListApi(data) { return $axios({ // 'url': '/shoppingCart/list', 'url': '/front/cartData.json', 'method': 'get', params:{...data} }) } 在 front目录下新增一个cartData.json' { "code": 1, "msg": null, "data": [], "map": {} } 后端:购物车模块实现 2.获取分类对应的菜品 【优化】 前端:已完成 后端: controller: 在DishController中重新定义一个list方法 1.调用service的查询方法 2.返回结果 service: 在DishService中定义一个查询方法 1.创建查询对象 2.设置查询条件:查询分类id、菜品名称name、菜品状态status 3.调用父类的查询方法,得到List<Dish> 4.构造List<DishDto>数据 5.循环遍历List<Dish>,将dish所有属性值拷贝给DishDto 6.查询口味信息列表,将其封装到dishDto中 7.将dishDto添加到List<DishDto> 8.返回List<DishDto>给controller dao: mp已提供 3.获取分类对应的套餐 前端:已完成 后端: controller: 在SetmealController中定义一个查询列表方法: 1.创建查询对象 2.设置查询条件(根据分类id查询) 3.调用service查询方法 4.返回结果 service: mp提供 dao: mp提供 购物车: 需求分析: 1.前端页面:/front/index.html 2.请求流程:用户登录成功后进入到首页---》选择相应的菜品或者套餐,添加到购物车---》发送请求到后端---》后端响应 点击购物车---》发送查询购物车的请求---》后端响应、点击购物车---》点击清空按钮---》发送删除购物车请求---》后端响应 请求梳理: 2.1添加购物车 【http://localhost:8080/shoppingCart/add + POST】 2.2查询购物车 【http://localhost:8080/shoppingCart/list + GET】 2.3清空购物车 【http://localhost:8080/shoppingCart/clean + DELETE】 3.接口设计: 添加购物车 接口路径:/shoppingCart/add 请求方式:POST 接口入参: 添加菜品:{"amount":78,"dishFlavor":"不要葱,微辣","dishId":"1397849739276890114","name":"辣子鸡","image":"xxx.jpg"} 添加套餐:{"amount":40,"setmealId":"1415580119015145474","name":"儿童套餐A计划","image":"xxx.jpg"} 封装到ShoppingCart对象中 接口响应:R<ShoppingCart> 购物车数据 查询购物车 接口路径:/shoppingCart/list 请求方式:GET 接口入参:无 【注意】:根据当前登录用户id进行查询当前用户下的所有购物车数据 接口响应:R<List<ShoppingCart>> 清空购物车 接口路径:/shoppingCart/clean 请求方式:DELETE 接口入参:无 【注意】:只能清空当前用户自己名下的购物车数据 接口响应:R<String> 清空成功|失败 4.数据模型: shopping_cart购物车表 代码准备: 后端: bean: ShoppingCart dao: ShoppingCartDao service: ShoppingCartService\ShoppingCartServiceImpl controller: ShoppingCartController 思路分析: 1.添加购物车 前端:已完成 后端: controller: 在ShoppingCartController中定义一个新增方法: 1.调用service的新增方法 2.返回结果 service: 在ShoppingCartService中定义一个新增方法: 1.查询购物车表是否已存在需要添加的商品 2.如果是新的商品,设置number数量为1, 4.如果不是新的商品,设置number数量+1 5.补齐字段:user_id、create_time 6.保存到购物车表中 dao: mp提供 2.查询购物车 前端: 还原请求 function cartListApi(data) { return $axios({ 'url': '/shoppingCart/list', // 'url': '/front/cartData.json', 'method': 'get', params:{...data} }) } 后端: controller: 在ShoppingCartController中定义一个list方法: 【注意】:根据当前登录用户id进行查询当前用户下的所有购物车数据 1.获取当前登录的用户id 2.设置查询条件 3.调用service的查询方法 4.返回结果 service: mp提供 dao: mp提供 3.清空购物车 前端:已完成 后端: controller: 在ShoppingCartController中定义一个删除方法: 【注意】:只能清空当前用户自己名下的购物车数据 1.获取当前登录的用户id 2.设置查询条件 3.调用service的删除方法 4.返回结果 service: mp提供 dao: mp提供 下单: 需求分析: 1.前端页面:/front/page/add-order.html 2.请求流程:用户登录进入移动端首页---》添加菜品或者套餐到购物车---》点击去结算---》立即触发两个请求【1.查询默认地址;2.查询购物车列表】 ---》可以添加备注信息、修改地址,点击去支付---》触发提交订单请求---》后端响应 请求梳理: 1.查询默认地址 已完成 【http://localhost:8080/addressBook/default + GET】 2.查询购物车列表 已完成 【http://localhost:8080/shoppingCart/list + GET】 3.提交订单请求 待实现 【http://localhost:8080/order/submit + POST】 3.接口设计: 提交订单请求 接口路径:/order/submit 请求方式:POST 接口入参:{"remark":"","payMethod":1,"addressBookId":"1629112905282654210"} json格式 考虑封装到Orders实体类中 接口响应:R<String> 提交成功|失败 4.数据模型: orders订单表 、order_detail订单明细表 orders:order_detail = 1:n 代码准备: 后端: bean: Orders、OrderDetail dao: OrdersDao、OrderDetailDao service: OrdersService|OrdersServiceImpl、OrderDetailService|OrderDetailServiceImpl controller: OrdersController 思路分析: 前端:已完成 后端: controller: 在OrdersController中定义一个提交订单方法: 1.调用service的提交订单方法 2.返回结果 service: 在OrdersService中定义一个提交订单方法: 0.开启事务(涉及到orders订单表 、order_detail订单明细表两张表的更新操作) 1.获取当前登录的用户id 2.查询用户表,得到用户信息 3.构造订单明细数据 List<OrderDetail> 3.1 查询购物车数据,根据当前用户id查,得到购物车列表 3.2 循环购物车列表,将购物车数据拷贝给OrderDetail 3.3 设置订单id 4.构造订单数据 Orders 4.1 补齐字段 4.2 设置总金额 5.调用orderDetailservice的保存方法,将订单明细数据保存到order_detail表中 6.调用自身的保存方法,将订单数据保存到orders表中 7.清空购物车 dao: mp已提供
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。