SpringBoot+MyBatis自定义拦截器实现参数拦截

MyBatis拦截器可以用来拦截参数、拦截Sql、拦截结果集等方式。
可以用来处理多租户、参数编码解码、参数过滤、sql监控等业务。
主要实现方式是由Mybatis提供的注解,并将类配置活注入到springBean中去
参考文章:MyBatis拦截器原理
业务需求:sql中的Like如果传参为%则会造成sql查询失效,传入的是%但是还是可以查到所有数据,不符合业务场景

  1. 创建查询参数拦截器Interceptor
package com.spm.common.security.interceptor;

import com.spm.common.core.utils.StringUtils;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.sql.PreparedStatement;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: ch
 * @time: 2022/7/1 16:07
 */
@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class)
})
//@Intercepts标明这是一个Mybatis拦截器类
//@Signature为具体拦截的位置 ParameterHandler为拦截参数
public class QueryExecutorInterceptor implements Interceptor {

    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
    private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取拦截器拦截的设置参数对象DefaultParameterHandler
        ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();

        // 通过mybatis的反射来获取对应的值
        MetaObject metaResultSetHandler = MetaObject.forObject(parameterHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, REFLECTOR_FACTORY);
        Object parameterObject = metaResultSetHandler.getValue("parameterObject");
        if (null != parameterObject) {
            //通过java反射获取到对象的读写方法
            List<PropertyDescriptor> propertiesList = getPropertiesList(parameterObject.getClass());
            Method readMethod;
            Method writeMethod;
            for (PropertyDescriptor property : propertiesList) {
                readMethod = property.getReadMethod();
                writeMethod = property.getWriteMethod();
                Object invoke = readMethod.invoke(parameterObject);
                if (null != invoke) {
                    String data = invoke.toString();
                    if (StringUtils.contains(data, "%")) {
                        System.out.println("拦截到参数为%号数据,已修改!");
                        writeMethod.invoke(parameterObject, StringUtils.escapeField(data));
                    }
                }

            }
            // 回写parameterObject对象
            metaResultSetHandler.setValue("parameterObject", parameterObject);
        }
        return invocation.proceed();
    }

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

    @Override
    public void setProperties(Properties properties) {

    }

    /**
     * 获取对象字段集合
     *
     * @param clazz 需要反射的对象类型
     * @return
     * @throws IntrospectionException
     */
    public static List<PropertyDescriptor> getPropertiesList(Class<?> clazz) throws IntrospectionException {
        List<PropertyDescriptor> descriptors = Arrays.stream(Introspector.getBeanInfo(clazz)
                .getPropertyDescriptors()).filter(p -> {
            String name = p.getName();
            //过滤掉不需要修改的属性
            return !"class".equals(name) && !"id".equals(name);
        }).collect(Collectors.toList());
        return descriptors;
    }
}

2.将拦截器注入到SpringBean工厂(我这块是用的spring.factories的注入方式,@Component应该也可以,只要将配置类注入就行)

package com.spm.common.security.config;

import com.spm.common.security.interceptor.QueryExecutorInterceptor;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @description:
 * @author: ch
 * @time: 2022/7/1 17:22
 */
public class MybatisConfig {
    @Bean
    ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return new ConfigurationCustomizer() {
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {
                configuration.addInterceptor(new QueryExecutorInterceptor());
            }
        };
    }
}

给百分号前边添加”\“转义符

通过拦截器解决要比手动在每个Controller毕竟更加简介明了,但是拦截和反射会消耗程序性能!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot中使用Mybatis拦截器的方法有三种。 第一种方法是在启动项目时不会自动调用自定义拦截器的setProperties方法。可以通过在SpringBoot的配置类中使用@Bean注解进行配置。 第二种方法是在Mybatis核心配置文件中配置拦截器的顺序。拦截器的顺序是从上往下的顺序,按照Executor、ParameterHandler、StatementHandler、ResultSetHandler的顺序进行拦截。 第三种方法是在application.yml或application.properties文件中进行配置。可以使用mybatis.interceptor属性指定拦截器的类名。 需要注意的是,在配置Mybatis拦截器时,config-location属性和configuration属性不能同时指定。根据具体需求,可以选择其中一种方式进行配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springBoot+mybatis简单demo完整详细版](https://download.csdn.net/download/u010962837/85226352)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [在springboot中给mybatis拦截器](https://blog.csdn.net/qq_43985303/article/details/130378043)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值