• 外卖项目05---套餐管理业务开发


    套餐:一组菜品的集合

    点击之后就会弹出下面的界面:

    上面是后台的管理操作,下面是处理完成后在用户端展示的界面效果:

    目录

    一、新增套餐 70

    1.1需求分析 70

    1.2数据模型 70

    1.3新增套餐---代码开发---准备工作&梳理交互过程 71

    1.3.1代码准备工作(类的导入,服务层的编写)71

    1.4新增套餐---代码开发---根据分类查询菜品 72

    1.5新增套餐---代码开发---服务端接收页面提交的数据 73

    1.6新增套餐---代码开发---保存数据到对应表 74

    1.7新增套餐---功能测试 75

    二、套餐信息分页查询 76

    2.1需求分析 76

    2.2代码开发---梳理交互过程 76

    2.3套餐信息分页查询---代码开发&功能测试 77

    三、删除套餐 (关联表之间的删除)78

    3.1需求分析 78

    3.2代码开发---梳理交互过程 78

    3.3删除套餐---代码开发&功能测试 79

    四、手机验证码登陆 80

    五、短信发送 81

    5.1短信服务介绍和阿里云短信服务介绍 81

    5.2短信发送---阿里云短信服务 82 

    5.2.1阿里云短信服务---注册账号 82

    5.3短信发送---代码开发---参照官方文档封装短信发送工具类 83

    六、手机验证码登陆 84 

    6.1需求分析 84

    6.2数据模型 84 

    6.3手机验证码登陆---代码开发---梳理交互过程&修改LoginCheckFliter 85

    6.3.1代码开发---梳理交互过程 85

    6.3.2代码开发---准备工作 85

    6.4手机验证码登陆---代码开发 86

    6.5手机验证码登陆---代码开发---登陆校验 86


    一、新增套餐 70

    1.1需求分析 70

    1.2数据模型 70

     

    1.3新增套餐---代码开发---准备工作&梳理交互过程 71

    1.3.1代码准备工作(类的导入,服务层的编写)71

    1.4新增套餐---代码开发---根据分类查询菜品 72

    1.3.1中的交互过程包含六次交互请求,前两次的请求交互在CategoryController中进行。

    选用其中的List集合中的数据信息。

    这两种类都在List中进行。

    实现的是下面的效果内容:

     本部分代码实现的效果: 

    本部分使用的代码如下所示:

    1. /**
    2. * 根据条件查询对应的菜品数据
    3. * @param dish
    4. * @return
    5. */
    6. @GetMapping("/list")
    7. public R> list(Dish dish){//这个部分传递的参数,可以是Long categoryid,
    8. // 但是可以将其进行扩展使用,使用Dish类中的参数,它包含了很多的参数信息,包含categoryid
    9. //构造查询条件
    10. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    11. queryWrapper.eq(dish.getCategoryId() != null , Dish::getCategoryId,dish.getCategoryId());
    12. //该部分是设置一个判断语句,确定id传递过来,并不是空的指针
    13. //添加排序条件
    14. queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
    15. //使用了两个判断条件,一个是根据sort进行升序排序,如果sort排序一致,再根据更新时间进行降序判断
    16. //添加条件,查询状态为1(起售状态)的菜品
    17. queryWrapper.eq(Dish::getStatus,1);
    18. List list = dishService.list(queryWrapper);//使用该方法,获取得到了一个集合
    19. return R.success(list);
    20. }

    1.5新增套餐---代码开发---服务端接收页面提交的数据 73

    下面部分代码开发实现的内容: 

     使用的是CommonController层的图片上传和下载的功能。

    下面本部分实现的是下面的效果:

    将客户端的数据信息发布反馈到后端当中:

    反馈到后端的内容数据信息: 

    本部分代码:

    1. /**
    2. * 新增套餐
    3. * @param setmealDto
    4. * @return
    5. */
    6. @PostMapping
    7. public R save(@RequestBody SetmealDto setmealDto){
    8. log.info("套餐信息: {}",setmealDto);
    9. return null;
    10. }

    1.6新增套餐---代码开发---保存数据到对应表 74

    套餐表中插入数据、套餐和菜品对应的关系表里面进行插入数据处理。这两个表都需要进行处理。

    对两张表的操作。

    在SetmealService接口中进行处理。

    本部分的代码如下所示:底层对两个表之间处理。

    步骤一:对SetmealService接口进行修改

    代码:

    1. /**
    2. * 新增套餐
    3. * @param setmealDto
    4. * @return
    5. */
    6. @PostMapping
    7. public R save(@RequestBody SetmealDto setmealDto){
    8. log.info("套餐信息: {}",setmealDto);
    9. return R.success("新增套餐成功");
    10. }

    步骤二:在SetmealServiceImpl驱动类中进行修改。

    1. /**
    2. * 新增套餐,同时需要保存套餐和菜品的关联关系
    3. * @param setmealDto
    4. */
    5. @Transactional
    6. public void saveWithDish(SetmealDto setmealDto) {
    7. //保存套餐的基本信息,操作setmeal,执行insert操作
    8. this.save(setmealDto);
    9. List setmealDishes = setmealDto.getSetmealDishes();
    10. setmealDishes.stream().map((item) -> {
    11. item.setSetmealId(setmealDto.getId());
    12. return item;
    13. }).collect(Collectors.toList());
    14. //保存套餐和菜品的关联信息,操作setmeal_dish,执行insert操作
    15. setmealDishService.saveBatch(setmealDishes);
    16. }

    1.7新增套餐---功能测试 75

    二、套餐信息分页查询 76

    2.1需求分析 76

    2.2代码开发---梳理交互过程 76

    一共能涉及到2次请求信息 

     注:

    1、中的name参数获取

     2、图片进行展示

    2.3套餐信息分页查询---代码开发&功能测试 77

            目前下面的代码能够实现主要的内容,但是在套餐分类的这一类当中是不进行显示的。是由于pageInfo中继承的泛型是Setmeal。

     但是Setmeal中不包含套餐分类的功能,只是返回的是套餐分类的id。

    本部分解决套餐分类中分类的类别显示问题:

    问题描述如下:

    本部分代码:

    1. /**
    2. * 套餐分页查询
    3. * @param page
    4. * @param pageSize
    5. * @param name
    6. * @return
    7. */
    8. @GetMapping("/page")
    9. public R page(int page,int pageSize,String name){//输入的是三部分的参数信息
    10. //分页构造器对象的创建
    11. Page pageInfo = new Page<>(page,pageSize);//分页构造器对象
    12. Page dtoPage = new Page<>();//使用SetmealDto中的内容对象,进行使用操作处理,
    13. // 由于SetmealDto继承Setmeal,并且还包含那个套餐分类的名称,所以使用该类
    14. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    15. //添加查询条件,根据name进行like模糊查询
    16. queryWrapper.like(name != null,Setmeal::getName,name);//括号内是进行条件的查询的判断,判断内容不为空,
    17. // 并且进行name模糊查询
    18. //添加排序条件,根据更新时间降序排序
    19. queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    20. setmealService.page(pageInfo,queryWrapper);
    21. //对象拷贝
    22. BeanUtils.copyProperties(pageInfo,dtoPage,"records");//是将pageInfo中的数据拷贝到dtoPage中
    23. //并且忽略pageInfo中的records的保存数据的信息记录。由于pageInfo中的泛型为Setmeal,
    24. //我们新创建的是dtoPage的泛型为SetmealDto,所以需要进行先排除
    25. List records = pageInfo.getRecords();//获取pageInfo中的records,对后面的这个records进行处理解决
    26. List list = records.stream().map((item) ->{
    27. SetmealDto setmealDto = new SetmealDto();
    28. //对象拷贝,因为创建的集合SetmealDto中是空的,所以需要将原来item的数据内容拷贝到新的SetmealDto中。
    29. BeanUtils.copyProperties(item,setmealDto);
    30. //分类id
    31. Long categoryId = item.getCategoryId();
    32. //根据分类id查询分类对象
    33. Category category = categoryService.getById(categoryId);
    34. if(category != null){
    35. //分类名称,获取套餐分类名称
    36. String categoryName = category.getName();
    37. setmealDto.setCategoryName(categoryName);//将查询到的categoryName添加到setmealDto中
    38. //因为创建的setmealDto是个新的集合,所以使用set进行添加到集合中
    39. }
    40. return setmealDto;
    41. }).collect(Collectors.toList());
    42. dtoPage.setRecords(list);
    43. return R.success(dtoPage);
    44. }

    三、删除套餐 (关联表之间的删除)78

    3.1需求分析 78

    需求:

    1、点击删除按钮删除商品

    2、批量删除商品的实现

    3、停售按键的正常使用,售卖的套餐不能被删除,停售后才能够被删除 

    3.2代码开发---梳理交互过程 78

     注:

    1、请求方式和请求地址是相同的

    2、区别在于两者的传递的id的个数不一样

    3.3删除套餐---代码开发&功能测试 79

    步骤一:在SetmealController层中进行书写删除的主代码

    1. /**
    2. * 删除套餐
    3. * @param ids
    4. * @return
    5. */
    6. @DeleteMapping
    7. public R delete(@RequestParam List ids){
    8. log.info("ids:{}",ids);
    9. // setmealService.removeWithDish(ids);
    10. return R.success("套餐删除成功");
    11. }

    步骤二:在SetmealSerice接口中创建新的方法

        public void removeWithDish(List list);

    步骤三:添加服务驱动类

    1. /**
    2. * 删除套餐,同时需要删除套餐和菜品的关联数据
    3. * @param ids
    4. */
    5. @Override
    6. public void removeWithDish(List ids) {
    7. //select count(*) from setmeal where id in (1,2,3) and status =1
    8. //查询套餐状态,确定是否可用删除
    9. LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
    10. queryWrapper.in(Setmeal::getId,ids);//是查询判断的第一部分条件是在(1,2,3)中进行查询进行表达
    11. queryWrapper.eq(Setmeal::getStatus,1);//判断条件等值查询判断,判断该商品的状态,1:在售;2:停售
    12. int count = this.count(queryWrapper);//ServiceImpl实现的框架下的一个count,封装生成
    13. if(count > 0 ){//异常提示报错,>0表示状态为1,处于售卖的状态。
    14. //如果不能被删除,抛出一个业务异常
    15. throw new CustomException("套餐正在售卖中,不能删除");
    16. }
    17. //如果可以删除,先删除套餐表中的数据---setmeal 这个是套餐(批量删除)
    18. this.removeByIds(ids);
    19. //删除关系表中的数据---setmeal_dish(关联数据)
    20. //创建一个新的处理方式,mysql中的编程处理的代码 delete from setmeal_dish where setmeal_id in (1,2,3...)
    21. LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
    22. lambdaQueryWrapper.in(SetmealDish::getSetmealId,ids);//该部分表示mysql的代码编写
    23. //删除关系表中的数据---setmeal_dish
    24. setmealDishService.remove(lambdaQueryWrapper);
    25. }

    步骤四:在主方法中进行调用使用该方法

    1. /**
    2. * 删除套餐
    3. * @param ids
    4. * @return
    5. */
    6. @DeleteMapping
    7. public R delete(@RequestParam List ids){
    8. log.info("ids:{}",ids);
    9. setmealService.removeWithDish(ids);
    10. return R.success("套餐删除成功");
    11. }

    四、手机验证码登陆 80

    五、短信发送 81

    5.1短信服务介绍和阿里云短信服务介绍 81

    5.2短信发送---阿里云短信服务 82 

    5.2.1阿里云短信服务---注册账号 82

     

     

    5.3短信发送---代码开发---参照官方文档封装短信发送工具类 83

    六、手机验证码登陆 84 

    6.1需求分析 84

    6.2数据模型 84 

    6.3手机验证码登陆---代码开发---梳理交互过程&修改LoginCheckFliter 85

    6.3.1代码开发---梳理交互过程 85

    6.3.2代码开发---准备工作 85

     修改部分一:

    修改部分二:

    6.4手机验证码登陆---代码开发 86

     本部分代码如下:

    代码:

    1. @Slf4j
    2. @RestController
    3. @RequestMapping("/user")
    4. public class UserController {
    5. @Autowired
    6. private UserService userService;
    7. public R sendMsg(@RequestBody User user, HttpSession session){
    8. //获取手机号
    9. String phone = user.getPhone();
    10. if (StringUtils.isNotEmpty(phone)){//首先进行条件判断
    11. //生成4位随机的验证码,通过ailiyun提供的功能类
    12. String code = ValidateCodeUtils.generateValidateCode(4).toString();
    13. log.info("code={}",code);
    14. //调用阿里云提供的短信服务API完成发送短信
    15. // SMSUtils.sendMessage("瑞吉外卖","",phone,code);
    16. //需要将生成的验证码保存到Session
    17. session.setAttribute(phone,code);
    18. return R.success("手机验证码短信发送成功");
    19. }
    20. return R.error("短信发送失败");
    21. }
    22. }

    6.5手机验证码登陆---代码开发---登陆校验 86

    使得前端能够进行登陆

    本部分代码:

    1. /**
    2. * 移动端用户登陆
    3. * @param map
    4. * @param session
    5. * @return
    6. */
    7. @PostMapping("/login")
    8. public R login(@RequestBody Map map, HttpSession session){//使用Map类
    9. log.info(map.toString());
    10. //获取手机号
    11. String phone = map.get("phone").toString();
    12. //获取验证码
    13. String code = map.get("code").toString();
    14. //从Session中获取保存的验证码
    15. Object codeInSession = session.getAttribute(phone);
    16. //进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)
    17. if(codeInSession != null && codeInSession.equals(code)){
    18. //如果能够对比成功,说明登陆成功
    19. LambdaQueryWrapper queryWrapper =new LambdaQueryWrapper<>();
    20. queryWrapper.eq(User::getPhone,phone);
    21. User user = userService.getOne(queryWrapper);
    22. if(user == null){
    23. //判断当前手机号对应的用户是否位新用户,如果是新用户就自动完成注册
    24. user = new User();
    25. user.setPhone(phone);
    26. user.setStatus(1);
    27. userService.save(user);
    28. }
    29. return R.success(user);
    30. }
    31. return R.error("登陆失败");
    32. }

    效果:实现在移动端进行登陆

    注:如果登陆时出现登陆不上的情况,可以尝试清理下浏览器的缓存,在进行登陆。

  • 相关阅读:
    有效管理token,充分发挥ChatGPT的能力
    AI 人工智能之常见概率分布(1)
    如何通过链路追踪进行定时任务诊断
    简单说明反射和new的区别和反射的使用代码展示
    十大经典排序算法之选择排序。
    介绍一下我们:久菜盒子工作室
    Layui快速入门之第五节 导航
    【linux】编译器使用
    [附源码]计算机毕业设计JAVA学生实习管理系统
    一文带你掌握 优先级队列
  • 原文地址:https://blog.csdn.net/xiaoxixicc/article/details/127974297