一、自定义注解

首先自定义注解,本文以添加和更新数据库数据为例,自定义@CreateBy和@UpdateBy注解,便于插入数据时自动注入创建人编号,更新数据时自动注入更新人编号。

以下是注解定义:

/**
 * 自动注入创建人的注解
 * @author zhifeng
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateBy {
    String value() default "";
}
/**
 * 自动注入更新人编号的注解
 * @author zhifeng
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface UpdateBy {
    String value() default "";
}

二、自定义mybatis插件的拦截器

/**
 * Mybatis自动注入拦截器
 *
 * @author zhifeng
 */
@EqualsAndHashCode
@Data
@Accessors(chain = true)
@Intercepts({@Signature(
        type = Executor.class,
        method = "update",
        args = {MappedStatement.class, Object.class})})
@Component
public class MybatisInjectInterceptor implements Interceptor {

    private Properties properties;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取登录对象
        LoginUser loginUser = UserContextHolder.get();

        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];

        // 获取sql命令
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        // 获取参数
        Object parameter = invocation.getArgs()[1];
        // 获取私有成员变量
        Field[] declaredFields = parameter.getClass().getDeclaredFields();
        if (parameter.getClass().getSuperclass() != null) {
            Field[] superField = parameter.getClass().getSuperclass().getDeclaredFields();
            declaredFields = ArrayUtils.addAll(declaredFields, superField);
        }

        // 遍历循环
        for (Field field : declaredFields) {

            // ========================= insert =========================
            // 创建人编号
            if (field.getAnnotation(CreateBy.class) != null) {
                if (SqlCommandType.INSERT.equals(sqlCommandType)) {
                    field.setAccessible(true);
                    field.set(parameter, String.valueOf(loginUser.getUserId()));
                }
            }

            // ========================= update =========================
            // 更新人编号
            if (field.getAnnotation(UpdateBy.class) != null) {
                if (SqlCommandType.INSERT.equals(sqlCommandType)
                        || SqlCommandType.UPDATE.equals(sqlCommandType)) {
                    field.setAccessible(true);
                    field.set(parameter, String.valueOf(loginUser.getUserId()));
                }
            }
        }

        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof Executor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties prop) {
        this.properties = prop;
    }
}

三、在MyBatisConfig中注册拦截器

 至此,代码书写完毕。

四、测试

在需要自动注入的字段上添加@CreateBy或者@UpdateBy注解

 

 测试添加一条数据,此时createBy和updateBy字段上都设置了操作人的编号

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐