实现MyBatis拦截器自动填充创建、更新时间等字段属性值

实现MyBatis拦截器自动填充创建、更新时间等字段属性值

lixiangrong
2024-01-03 / 0 评论 / 14 阅读 / 正在检测是否收录...

实现MyBatis拦截器自动填充创建、更新时间等字段属性值

1.创建DataFill注解

package com.risesun.common.core.annotation;

import org.apache.ibatis.mapping.SqlCommandType;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author LiXiangrong
 * @Description 这是用来默认填充的注释 value支持spel表达式
 * @Date 2023/03/13 16:30:45
 **/
@Documented
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DataFill
{

    String value();

    /**
     * 填充的类型
     * @return
     */
    Class fillClass();

    /**
     * sql插入类型
     * @return 返回数组
     */
    SqlCommandType[] commandTypes();
}

2.格式化方法Func

package com.risesun.common.core.utils;

import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @Author LiXiangrong
 * @Description 公用函数类
 * @Date 2023/03/13 14:13:20
 **/
public class Func
{
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(Func.class);

    /**
     * @Author LiXiangrong
     * @Description 构造函数私有化
     * @Date 2023/03/13 17:09:38
     **/
    private Func()
    {
    }

    /**
     * @Author LiXiangrong
     * @Description 安全的进行字符串 format
     * @Date 2023/03/13 16:09:13
     * @Param target
     * @Param params
     * @Return java.lang.String
     **/
    public static String formatStr(String target, Object... params)
    {
        if (target.contains("%s") && ArrayUtils.isNotEmpty(params))
        {
            return String.format(target, params);
        }
        return target;
    }
}

3.SPEL表达式的定义

// 自动插入创建时间和更新时间按SPEL表达式
    public static final String DATE_DEFAULT_SPEL = "T(com.risesun.common.core.utils.DateUtil).getCurrentDate()";

    // 自动插入登录用户名按SPEL表达式
    public static final String USERNAME_DEFAULT_SPEL = "T(com.risesun.common.security.utils.SecurityUtils).getUsername()";

    // 自动填充UUID
    public static final String UUID_DEFAULT_SPEL = "T(com.risesun.common.core.utils.uuid.IdUtils).randomUUID()";

    // 自动填充雪花算法ID
    public static final String ASSIGN_ID = "T(com.risesun.business.util.CommonUtils).assignId()";

    // 自动填充登陆人id(Long类型)
    public static final String USER_ID = "T(com.risesun.common.security.utils.SecurityUtils).getUserId()";

    // 自动填充登陆人id(String类型)
    public static final String USERID_DEFAULT_SPEL = "T(com.risesun.common.security.utils.SecurityUtils).getUserId().toString()";

4.创建自定义AutoFillInterceptor拦截器实现Mybatis的拦截器接口

package com.risesun.business.config;

import com.risesun.common.core.annotation.DataFill;
import com.risesun.common.core.utils.Func;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

/**
 * @Author LiXiangrong
 * @Description MyBatis拦截器填充属性值
 * @Date 2023/03/13 17:00:33
 **/
@Component
@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class AutoFillInterceptor implements Interceptor
{
    public static final Logger log = LoggerFactory.getLogger(AutoFillInterceptor.class);
    public static final ExpressionParser SPEL_EXPRESSION = new SpelExpressionParser();

    @Override
    public Object intercept(Invocation invocation) throws Throwable
    {
        Object[] params = invocation.getArgs();
        MappedStatement mappedStatements = (MappedStatement) params[0];
        SqlCommandType sqlCommandType = mappedStatements.getSqlCommandType();
        log.info("开始自动填充...");
        setDefaultValue(params[1], sqlCommandType);
        return invocation.proceed();
    }

    /*
     * @Author LiXiangrong
     * @Description setDefaultValue
     * @Date 2023/03/13 17:02:17
     * @Param metaObject
     * @Param sqlCommandType
     * @Return void
     **/
    private void setDefaultValue(Object metaObject, SqlCommandType sqlCommandType)
    {
        Expression expression;
        List<Field> needFillList = new ArrayList<>();
        //找到所有有DataFill注解的属性
        ReflectionUtils.doWithFields(metaObject.getClass(), needFillList::add, getFieldFilter(sqlCommandType));

        //将所有的属性进行赋值
        for (Field field : needFillList)
        {
            DataFill fill = field.getAnnotation(DataFill.class);
            if (null != fill)
            {
                expression = SPEL_EXPRESSION.parseExpression(fill.value());
                Object fillObj = expression.getValue();
                if (fill.fillClass().isInstance(fillObj))
                {
                    ReflectionUtils.makeAccessible(field);
                    ReflectionUtils.setField(field, metaObject, fillObj);
                    //this.setFieldValByName(field.getName(), fillObj, metaObject);
                } else
                {
                    throw new RuntimeException(Func.formatStr("默认值填充错误,{}的类型应该为{},传入的类型与其不兼容", field.getName(), fill.fillClass().getName()));
                }
            }
        }
    }

    /**
     * @Author LiXiangrong
     * @Description getFieldFilter
     * @Date 2023/03/13 17:03:07
     * @Param sqlCommandType
     * @Return org.springframework.util.ReflectionUtils.FieldFilter
     **/
    private ReflectionUtils.FieldFilter getFieldFilter(SqlCommandType sqlCommandType)
    {
        return field ->
        {
            DataFill fill = field.getAnnotation(DataFill.class);
            if (null == sqlCommandType)
            {
                return false;
            }
            return (fill != null && Arrays.asList(fill.commandTypes()).contains(sqlCommandType));
        };
    }

    @Override
    public Object plugin(Object target)
    {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties)
    {
        Interceptor.super.setProperties(properties);
    }
}
0

评论 (0)

取消