JavaWeb合集17-简化开发—公共字段自动填充
十七、简化开发
1、公共字段自动填充
需求:很多时候,数据库表都有一些公共的字段,如:创建时间、修改时间、修改人ID等,这些字段每次都要去获取对应的日期或者用户ID,填充到要添加的字段中,比较麻烦,这时就可以使用自动填充。
技术点:枚举、注解、AOP、反射
实现思路,及实现:
-
自定义注解AutoFil,用于标识需要进行公共字段自动填充的方法
/** * 数据库操作类型枚举 */ public enum OperationType { UPDATE, INSERT, }
/** * 自定义注解,用于标识需要自动填充的字段 */ //操作类型只能是在方法上 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AutoFill { //数据库操作类型,枚举:Update、Insert OperationType value(); }
-
自定义切面类AutoFillAspect,统一拦截加入了AutoFill 注解的方法,通过反射为公共字段赋值
/** * 自定义切面类:实现公共字段的填充 */ @Aspect @Component @Slf4j public class AutoFillAspect { // 切入点:拦截所有fun.yhzy.mapper包下的全部类或接口,再是全部方法,但是方法上必须存在AutoFill注解 @Pointcut("execution(* fun.yhzy.mapper.*.*(..)) && @annotation(fun.yhzy.annotation.AutoFill)") public void autoFillPointcut(){ } /** * 前置通知 * @param joinPoint * @return */ @Before("autoFillPointcut()") public void autoFillBefore(JoinPoint joinPoint) { log.info("公共字段填充"); //1、获取到当前被拦截的方法上的数据库操作类型 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();//方法签名对象 AutoFill autoFill= methodSignature.getMethod().getAnnotation(AutoFill.class); //获取方法上的注解对象 OperationType operationType = autoFill.value(); //获取注解上的数据库操作类型的值 //2、获取到当前被拦截的方法的参数--实体对象 Object[] args = joinPoint.getArgs(); //获取到当前加了注解方法上的全部参数 if (args.length==0 || args==null){ return; } Object arg = args[0]; //获取拦截方法的第一个参数(熟尘约定:实体参数放在第一个) //3、准备需要传入的值 Long currentId = BaseContext.getCurrentId(); //操作人的id LocalDateTime now = LocalDateTime.now(); //当前日期时间 //4、根据数据库操作类型,为对应的属性通过反射来赋值 if(operationType==OperationType.INSERT){ try{ //插入操作:为创建时间、创建人、更新时间、更新人赋值,4个公共字段 Method createTimeMethod = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME,LocalDateTime.class); Method updateTimeMethod = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,LocalDateTime.class); Method createUserMethod =arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER,Long.class); Method updateUserMethod = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class); //通过反射来为对应的属性赋值(对象是:arg,值是第3步获取到的值) createTimeMethod.invoke(arg,now); updateTimeMethod.invoke(arg,now); createUserMethod.invoke(arg,currentId); updateUserMethod.invoke(arg,currentId); }catch (Exception e){ e.printStackTrace(); } } else if (operationType==OperationType.UPDATE) { // 更新操作:为更新时间、更新人赋值 ,2个公共字段 try{ Method updateTimeMethod = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,LocalDateTime.class); Method updateUserMethod = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class); updateTimeMethod.invoke(arg,now); updateUserMethod.invoke(arg,currentId); }catch (Exception e){ e.printStackTrace(); } } } }
-
在Mapper的方法上加入AutoFill 注解
@Mapper public interface CategoryMapper { //添加菜品分类 @Insert("insert into tb_category(name, type, sort, status, create_time, update_time, create_user, update_user) " + "values (#{name},#{type},#{sort},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})") @AutoFill(value=OperationType.INSERT) int addCategory(Category category); //根据ID修改菜品分类 @AutoFill(value=OperationType.UPDATE) int updateCategoryById(Category category); }