黑马 - 苍穹外卖 Day03

本文介绍了如何通过自定义注解AutoFill和切面类AutoFillAspect解决多表或多实体类中公共字段的自动填充问题,通过注解标识需要赋值的方法,并在切点拦截器中根据不同操作类型动态为实体对象的公共字段赋值。
摘要由CSDN通过智能技术生成

一、公共字段填充

问题:多个表存在多个相同的字段,多个实体类中存在多个相同的属性
在这里插入图片描述

解决方法: 在这里插入图片描述

  • 自定义注解 AutoFill,用于标识需要进行公共字段自动填充方法
  • 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill注解的方法,通过反射为公共字段赋值
  • 在Mapper层的方法上加上注解

为什么要使用注解?

通过切面来统一拦截赋值,存在的是问题 不是每个持久层的方法都需要被拦截赋值,如:select操作,所以在程序中需要有一种技术能够知道当前持久层是什么操作,需不需要为这些公共字段来设置值,加入注解后,就是相当于打上了一个标识,表示我们当前这个方法需要被拦截,需要为这几个公共字段来赋值

代码实现:

  1. AutoFill注解实现
// AutoFill 注解
package com.sky.anotation;

import com.sky.enumeration.OperationType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/*
 * @Description  表明哪些Mapper层的哪些方法需要被自动填充
 */

// 表明当前注解加在什么位置
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

    // 数据库操作类型: UPDATE INSERT
    OperationType value();
}
  1. AutoFIllAspect切面类
package com.sky.aspect;

import com.sky.anotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/*
 * @Author 海棠
 * @Description  切面类,统一拦截加入了 AutoFill 注解的方法
 * 自定义切面,实现公共字段自动填充处理逻辑
 * @Date 9:18 2024/3/7
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    // 切入点
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.anotation.AutoFill)")
    public void autoFillPointCut() {
    }

    // 前置通知
    // 在insert、update之前为公共字段赋上值,如果是其他的,
    // 在SQL执行完之后,在进行赋值毫无意义

    @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 == null || args.length == 0) {
            return;
        }

        // 约定:被填充的对象在传参时需要排在第一位
        Object entity = args[0];

        // 准备赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

        // 根据当前不同的操作类型,为对应的属性通过反射来进行赋值
        if (operationType == OperationType.INSERT) {
            // 为4个公共字段赋值
            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) {
                e.printStackTrace();
            }
        } else if(operationType == OperationType.UPDATE) {
            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) {
                e.printStackTrace();
            }
        }

    }
}
  1. 在需要被自动填充公共字段的Mapper方法上添加 @AutoFill注解即可完成自动填充功能

二、新增菜品

2.1 文件上传接口开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值