一、公共字段填充
问题:多个表存在多个相同的字段,多个实体类中存在多个相同的属性
解决方法:
- 自定义注解 AutoFill,用于标识需要进行公共字段自动填充方法
- 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill注解的方法,通过反射为公共字段赋值
- 在Mapper层的方法上加上注解
为什么要使用注解?
通过切面来统一拦截赋值,存在的是问题 不是每个持久层的方法都需要被拦截赋值,如:select操作,所以在程序中需要有一种技术能够知道当前持久层是什么操作,需不需要为这些公共字段来设置值,加入注解后,就是相当于打上了一个标识,表示我们当前这个方法需要被拦截,需要为这几个公共字段来赋值
代码实现:
- 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();
}
- 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();
}
}
}
}
- 在需要被自动填充公共字段的Mapper方法上添加 @AutoFill注解即可完成自动填充功能
二、新增菜品
2.1 文件上传接口开发
…