SpringBoot项目开发中公共字段的处理
序言
在SpringBoot项目开发中,会存在许多重复的公共字段,例如:
| 字段名 |
|---|
| create_time 创建时间 |
| update_time 更新时间 |
| create_user 创建操作人 |
| update_user 更新操作人 |
对于以上四个字段,需要大量的重复代码来实现,比较繁琐、冗余。
一、利用注解+AOP+反射处理公共字段
1.1核心思路
以上四个字段只会出现在更新(update)和插入(insert)操作之上,我们可以创建一个注解,然后在创建一个aop切面,利用aop来捕获注解,再使用反射,将四个字段进行赋值。
1.2代码实现
- 创建注解
//自定义注解
@Target(ElementType.Method)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill{
//数据库操作类型
OperationType value();
}
- 创建一个枚举,提高代码的可读性和可维护性
public enum OperationType {
UPDATE,
INSERT
}
- 创建一个AOP切面,捕捉注解
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
//切入点
@Pointcut("excution(* com.yourpackage,*.*(,,)) && @annotation(com.yourpackage.AutoFill)")
public void autoFillPointCut(){}
}
- 创建通知,通知中使用反射实现功能
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
//切入点
@Pointcut("excution(* com.yourpackage,*.*(,,)) && @annotation(com.yourpackage.AutoFill)")
public void autoFillPointCut(){}
//前置通知
@Before("autoFillPointCut()")
public void autoFill(JointPoint jointpoint){
try{
//日志记录
log.info("开启公共字段自动填充");
//利用反射获取注解
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);
OperationType value = autoFill.value();
//利用反射获取方法上的参数
Object[] args = joinPoint.getArgs();
//判断,如果mapper方法上不存在Insert或者Update枚举,或者读取不到参数,则直接结束
if(value == null || arg){
return;
}
// 获取第一个参数作为实体对象
Object entity = args[0];
// 设置创建时间和更新时间
LocalDateTime now = LocalDateTime.now();
setFieldIfExists(entity, "createTime", now);
setFieldIfExists(entity, "updateTime", now);
// 设置创建用户和更新用户
Long userId = getUserId(); // 获取当前用户ID的方法,未给出具体的值,自定义
setFieldIfExists(entity, "createUser", userId);
setFieldIfExists(entity, "updateUser", userId);
} catch(Exception e){
log.error("自动填充失败:{}",e.getMessage());
e.printStackTrace();
}
//设置实体字段
public void setFieldIfExists(Object entity, String filedName, Object vaule) throw NoSuchFieldException, IllegalAccessException {
try{
Filed field = entity.getClass().getDeclaredField(fileName);
//避免安全扫描出现警告,覆盖访问控制
ReflectionUtils.makeAccessible(field);
field.set(entity, value)
} catch (NoSuchFiledException e){
log.warn("字段{}不存在,无法设置值",filedName);
}
}
}
}