苍穹外卖【day3|菜品管理】

🌈个人主页 :一条泥憨鱼 (欢迎各位大佬莅临)

🎬精选专栏:数据结构与算法Java,AI与Agent

今天与大家一同学习苍穹外卖day03(菜品管理)。

公共字段自动填充:

这是一个偏技术而非业务的需求

问题分析和实现思路:

我们想要在调用到某些操作类型的时候就对公共字段进行自动填充(更新)

先创建一个包,将所有注解放在这个包下面,并枚举操作类型

接下来创建切面

在Mapper方法上加入注解

JoinPoint 参数

  • 作用:封装了当前连接点(被拦截方法)的信息

对于以下四个字段,使用update和insert方法时要重新赋值的字段不同

切面设计代码完整版

java 复制代码
@Aspect  //加这个注解声明是切面
@Component //本质仍是bean对象,要交给spring管理
@Slf4j    //方便日志记录
public class AutoFillAspect {
    //切面由切入点和通知(用于代码增强)组成
    //切入点
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    //execution内为要拦截的地方
    public void autoFillPointCut() {
    }

    //前置通知,进行公共字段的填充
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) {
        log.info("开始进行公共字段填充..");
        //获取到当前拦截到的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
        OperationType operationType = autoFill.value();//获得数据库操作类型
        //获取到当前被拦截方法的参数--实体对象
        Object[] args = joinPoint.getArgs();
        if (args.length == 0 || args == null) {
            return;
        }
        Object entity = args[0];
        //准备为字段赋值的数据
        LocalDate now = LocalDate.now();
        Long currentId = BaseContext.getCurrentId();
        //根据当前不同的操作类型,为对应的属性通过反射来获取
        if (operationType == OperationType.INSERT) {
            try {
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //通过反射为对象赋值
                setCreateTime.invoke(entity, now);
                setCreateUser.invoke(entity, currentId);
                setUpdateTime.invoke(entity, now);
                setUpdateUser.invoke(entity, currentId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else if (operationType == OperationType.UPDATE) {
            //为2个公共字段赋值
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                
                //通过反射为对象赋值
                setUpdateTime.invoke(entity, now);
                setUpdateUser.invoke(entity, currentId);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

拦截方法

获取方法签名

获取@AutoFill注解

获取操作类型(INSERT/UPDATE)

获取方法参数

获取实体对象

准备填充数据

通过反射填充字段

在categoryMapper中也应该加上注解

复制代码

至此,我们已经可以通过设计的切面对象实现公共字段自动填充

所以在service的impl里面的save和update方法就不需要再保留为公共字段赋值的部分了

我们直接将其注释掉

以后只需要在Mapper里的方法上加注解就可以了

新增菜品------需求分析和设计

业务规则

接口设计

根据类型查询分类,这里因为是新增菜品,所以请求参数统一用1

文件上传

新增菜品

数据库设计

文件上传接口设计

根据接口文档的名称以及命名规范,我们要新建一个Controller类,Common表示通用,新增菜品结束,后续也可能会用上

controller层代码的实现(阿里云OSS的启动需要回顾JavaWeb148集的知识)

  1. CommonController的upload方法主要是调用AliOssUtil(阿里云OSS工具类)来上传文件
  2. 文件上传到云存储后,返回的是文件访问路径
  3. 这个操作不涉及数据库操作,所以不需要Mapper层
  4. 由于业务逻辑很简单(只是调用工具类上传),所以也省略了Service层

不是所有功能都需要Service和Mapper层,这是合理的架构设计:

  1. 工具类操作(如文件上传、短信发送、邮件发送):直接使用工具类
  2. 业务逻辑操作(如用户管理、订单处理):使用Service + Mapper层
  3. 第三方服务调用(如支付接口、地图服务):直接调用API或使用工具类

新增菜品接口设计

在controller层新增dishcontroller,代码设计如下

service层代码设计

返回改善controller层代码

在service层声明方法

impl层的实现

后续Mapper接口和xml文件的代码实现都比较简单,这里就不多解释了

菜品分页查询

需求分析和设计

注意:categoryName字段是来自category表

代码开发

由于categoryName不是来自菜品表,所以要设计VO,使用分类名称字段,使得前端能正常展示数据

接下来在controller层编写代码

爆红是因为service层并无此方法,所以我们去service层实现该方法

然后我们去impl实现类实现此方法。既然是分页查询,那就又要用上我们的PageHelper了

java 复制代码
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO){
        PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
        Page<DishVO> page=dishMapper.pageQuery(dishPageQueryDTO);
        return new PageResult(page.getTotal(),page.getResult());
    }

对应xml文件的代码如下

在接口文档进行调试的时候,如果状态码爆401,记得去员工登录处获取新token

删除菜品

需求分析和设计

我们把删除一个也算进批量删除中

接口设计

数据库设计

这里需要操作的数据库较多

代码开发

controller层

加RequestParam注解表示由MVC框架自动将参数转化为一个集合

(注意:这里括号内是Long不是long)

在service层扩展方法

在impl层具体实现

java 复制代码
//菜品批量删除
    @Transactional
    public void deleteBatch(List<Long> ids){
        //判断当前菜品是否能够删除---是否存在起售中菜品
        for (Long id : ids) {
            Dish dish=dishMapper.getById(id);
            if(dish.getStatus()== StatusConstant.ENABLE){
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }
        //判断当前菜品是否能够删除---是否被套餐关联
        List<Long> setmealIds=setmealDishMapper.getSetmealIdsByDishIds(ids);
        if(setmealIds!=null&&setmealIds.size()>0){
            //当前套餐被关联了,不能删除
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        //删除菜品表中的菜品数据
        for (Long id : ids) {
            dishMapper.deleteById(id);
            //删除菜品关联的口味数据
            dishFlavorMapper.deleteByDishId(id);
        }




    }

后续Mapper层和xml文件的实现也都比较常规,不多赘述

修改菜品

需求分析和设计

代码实现

根据id查询菜品

controller层(爆红处记得传入参数id,这里主包失误了,后面才发现)

service层

service实现层

mapper层方法的实现

修改菜品

controller

service

service实现层

mapper层

由于这里比较复杂,所以我们去xml文件里编写动态sql

至此,修改菜品的代码开发我们已经实现完毕

相关推荐
Wenzar_1 小时前
Playwright 实战:高可信 UI 回归验证流水线
java·ui
livemetee1 小时前
Java 25虚拟线程使用实例
java
andafaAPS1 小时前
安达发|金属加工企业如何靠生产计划排单软件打破产能困局?
数据库·aps生产排程·安达发aps·生产计划排单软件·计划排产软件
云烟成雨TD1 小时前
Spring AI 1.x 系列【43】基于标准输入输出 (STDIO) 与服务端推送事件 (SSE) 的 MCP 服务端
java·人工智能·spring
va学弟1 小时前
Java 网络通信编程(9):从 BIO 到 NIO
java·运维·服务器·网络
凡人叶枫1 小时前
Effective C++ 条款05:了解 C++ 默默编写并调用哪些函数
java·linux·开发语言·c++·effective c++·编程范式
Full Stack Developme1 小时前
G1回收器的工作机制
java·jvm
砍材农夫1 小时前
物联网实战:Spring Boot + Netty 搭建 MQTT平台 | 多协议适配与模块化设计
java·spring boot·后端·物联网·spring
云烟成雨TD1 小时前
Spring AI 1.x 系列【41】接入高德 MCP 服务
java·人工智能·spring