mybatis(mybatis-plus)使用sql拦截器和自定义注解获取sql和参数

 注解 SqlLogs

package com.ruoyi.common.annotation;

import java.lang.annotation.*;

/**
 * 获取sql注解
 *
 * @author ruoyi
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SqlLogs
{
    /**
     * 是否打印sql
     */
    public boolean hasSqlLog() default false;



}

 sql拦截器 SqlLogsInterceptor   *参数还没处理*

package com.ruoyi.framework.config;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;

import com.ruoyi.common.annotation.SqlLogs;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.statement.Statement;
import org.apache.commons.collections4.functors.ConstantFactory;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
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 javax.annotation.Resource;
import javax.sql.DataSource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.StampedLock;


@Slf4j
@AllArgsConstructor
//@Aspect
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Component
public class SqlLogsInterceptor extends AbstractSqlParserHandler implements Interceptor {

    private DataSource dataSource;

    private final StampedLock lock = new StampedLock();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Map<String,Object> sqlMap = new HashMap<>();
        Boolean hasSqlLogs = false;
        StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        this.sqlParser(metaObject);
        // 先判断是不是SELECT操作 不是直接过滤
        MappedStatement mappedStatement =
                (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
            return invocation.proceed();
        }
        //获取注解  来判断是否储存sql
        final Object[] args = invocation.getArgs();
        //获取执行方法的位置
        String namespace = mappedStatement.getId();
        //获取mapper名称
        String className = namespace.substring(0,namespace.lastIndexOf("."));
        //获取方法名
        String methedName= namespace.substring(namespace.lastIndexOf(".") + 1,namespace.length());
        //获取当前mapper 的方法
        Method[] ms = Class.forName(className).getMethods();
        for(Method m : ms){
            if(m.getName().equals(methedName)){
                SqlLogs annotation = m.getAnnotation(SqlLogs.class);
                if(annotation != null){
                    hasSqlLogs = annotation.hasSqlLog();
                }
            }
        }
        //如果是有注解值为true,便获取sql处理参数
        if(hasSqlLogs){
            BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
            // 执行的SQL语句
            String originalSql = boundSql.getSql();
            // SQL语句的参数
            Object parameterObject = boundSql.getParameterObject();
            if(parameterObject != null){
                Field[] fields = parameterObject.getClass().getFields();
                if(fields != null && fields.length>0){
                    for(Field field:fields){
                        field.setAccessible(true);
                        System.err.println("获取参数: "+field.getName());
                        // sqlMap.put(field.getName(),field.get());
                    }
                }
            }
            System.err.println("sql :"+originalSql);
        }
        //originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + 1 + " in (" + 2 + ")";
        // metaObject.setValue("delegate.boundSql.sql", originalSql);
        return invocation.proceed();

    }

    /**
     * 生成拦截对象的代理
     *
     * @param target 目标对象
     * @return 代理对象
     */
    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

}

 在MybatisPlusConfig中注册bean

    @Bean
    @ConditionalOnMissingBean //有此实例便不进行注册
    public SqlLogsInterceptor dataScopeInterceptor(DataSource dataSource) {
        return new SqlLogsInterceptor(dataSource);
    }

 

 在mapper中使用注解

    @SqlLogs(hasSqlLog = true)
    List<XgYyxxVo> selectByLqw(@Param(Constants.WRAPPER) Wrapper queryWrapper);

 效果

mybatis(mybatis-plus)使用sql拦截器和自定义注解获取sql和参数

mybatis(mybatis-plus)使用sql拦截器和自定义注解获取sql和参数

上一篇:如何在数据库中进行RBAC权限应用


下一篇:Hive的JDBC连接配置