完整代码在我的gitee仓库中(主页有地址),需要的码友可以自行下载使用!
编写不易,如若帮助到你,请帮我点个赞吧!谢谢!!!
1、公共字段自动填充
(1)问题分析
(2)代码开发一
1、annotation/AutoFill.java创建
1、创建包和类:sky-server/src/main/java/com/sky/annotation/AutoFill.java
填充的代码为:
package com.sky.annotation;
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;
/**
* 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
* @author sky
* @Target:可使用的值定义在ElementType枚举类中,常用值如下:TYPE,类,接口 / FIELD, 成员变量 / METHOD, 成员方法
*/
@Target(ElementType.METHOD)//表示注解只能作用于方法上.
@Retention(RetentionPolicy.RUNTIME)//表示注解在运行时可以获取
public @interface AutoFill {
//OperationType导入包的位置:sky-common/src/main/java/com/sky/enumeration/OperationType.java
OperationType value();//自定义数据库操作类型,如UPDATE、INSERT
}
2、aspect/AutoFillAspect.java创建
位置:sky-server/src/main/java/com/sky/aspect/AutoFillAspect.java
具体代码:
package com.sky.aspect;
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.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointcut() {}
/**
* 前置通知,在通知中进行自动字段的赋值
*/
@Before("autoFillPointcut()")
public void autoFill(JoinPoint joinPoint) {
log.info("开始进行公共字段自动填充...");
}
}
示意图:
3、添加代码
位置:sky-server/src/main/java/com/sky/mapper/EmployeeMapper.java
添加的代码:
第一条:
@AutoFill(value = OperationType.INSERT)
第二条:
@AutoFill(value = OperationType.UPDATE)
示意图:下图的33行和47行位置
3、测试自定义切面类(通知类)
打上断点,启动(DeBug)项目,打开前端网页添加员工
在图示位置输入数据,点击保存
回到控制台查看,发现已成功拦截插入(insert)员工信息
(3)代码开发二
1、AutoFillAspect代码完善
位置:sky-server/src/main/java/com/sky/aspect/AutoFillAspect.java
具体代码:
package com.sky.aspect;
import com.sky.annotation.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;
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
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();
//为了方便,约定使用注解时,第一个参数的类型是实体类
Object entity = args[0];
//准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根据数据库操作类型,进行赋值
if (OperationType.UPDATE.equals(operationType)) {
//更新操作,需要更新更新时间
try {
//为2个公共字段赋值
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();
}
} else if (OperationType.INSERT.equals(operationType)) {
//插入操作,需要插入创建时间和更新时间
try {
//为4个公共字段赋值
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
//设置更新时间
setUpdateTime.invoke(entity, now);
//设置更新用户
setUpdateUser.invoke(entity, currentId);
//设置创建时间
setCreateTime.invoke(entity, now);
//设置创建用户
setCreateUser.invoke(entity, currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
log.info("公共字段自动填充完成...");
}
}
示意图:
2、EmployeeServiceImpl注销公共属性代码
注意:注销到涉及到insert、update方法的公共属性(时间和修改人ID)
文件位置:sky-server/src/main/java/com/sky/service/impl/EmployeeServiceImpl.java
代码位置:
3、CategoryServiceImpl注解公共属性代码
注意:注解掉涉及到insert、update方法的公共属性(时间和修改人ID)
文件位置:sky-server/src/main/java/com/sky/service/impl/CategoryServiceImpl.java
代码位置:
4、功能测试(前后端联调)
(1)设置断点,启动(DeBug)项目
(2)打开前端网页工作台
(3)选择“员工管理”|任意选择一名员工进行“修改”操作|填写修改信息|点击“保存”,查看控制台信息
按F8或者F6,执行下一步,信息显示已拦截到com.sky.mapper.EmployeeMapper.update(com.sky.entity.Employee); 即“update”方法
方法类型为“Update”
获取具体的员工
跳过断点
员工信息已发生改变,至此,公共字段自动填充功能已完成!