Mybatis-Plus对select中模糊查询%转义插件

1. 自定义插件 CharEscapeInnerInterceptor,继承InnerInterceptor

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.SneakyThrows;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;

/**
 * @author : yx-0176
 * @description
 * @date : 2021/12/6
 */
public class CharEscapeInnerInterceptor implements InnerInterceptor {

    Logger log = LoggerFactory.getLogger(CharEscapeInnerInterceptor.class);

    private CharEscape charEscape = new CharEscapeImpl();

    public CharEscapeInnerInterceptor() {
    }

    public CharEscapeInnerInterceptor(CharEscape charEscape) {
        this.charEscape = charEscape;
    }

    @PostConstruct
    public void init() {
        log.info("CharEscapeInnerInterceptor is plugins of mybatis-plus initd");
    }

    @SneakyThrows
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        log.info("CharEscapeInnerInterceptor is plugins of mybatis-plus paramer before update: {}", parameter.toString());
        if (parameter instanceof MapperMethod.ParamMap) {
            MapperMethod.ParamMap map = (MapperMethod.ParamMap) parameter;
            for (Object key : map.keySet()) {
                Object obj = map.get(key);
                if (obj != null) {
                    if (obj instanceof AbstractWrapper) {
                        // Mybatis-plus的Wrapper查询参数lambda
                        getObjCharEscape(((AbstractWrapper) obj).getParamNameValuePairs());

                        // Mybatis-plus的Wrapper查询参数
                        getObjCharEscape(((AbstractWrapper) obj).getEntity());
                    } else {
                        getObjCharEscape(obj);
                    }
                }
            }
        } else if (parameter instanceof String) {
            getObjCharEscape(parameter);
        }
        log.info("CharEscapeInnerInterceptor is plugins of mybatis-plus paramer after update:{}", parameter);
    }


    public Object getObjCharEscape(Object object) throws Exception {
        if (object instanceof Long) {
            return object;
        }
        if (object instanceof String) {
            // 反射修改参数值
            Field f = object.getClass().getDeclaredField("value");
            f.setAccessible(true);
            f.set(object, charEscape.charEscape(object.toString()).toCharArray());
            return object;
        }
        if (object instanceof Map) {
            Map map = (Map) object;
            for (Object o : map.keySet()) {
                map.put(o.toString(), getObjCharEscape(map.get(o)));
            }
            return map;
        }
        if (object instanceof Collection) {
            for (Object o : ((Collection) object)) {
                getObjCharEscape(o);
            }
            return object;
        }
        for (Field field : object.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            // 判断是否为final
            if (Modifier.isFinal(field.getModifiers())) {
                continue;
            }
            Object o = field.get(object);
            if (Objects.isNull(field.get(object))) {
                continue;
            }
            field.set(object, getObjCharEscape(o));
        }
        return object;
    }


    public interface CharEscape {

        /**
         * 转义方法
         *
         * @param charString 需要转义的字字符
         * @return
         */
        String charEscape(String charString);
    }

    private class CharEscapeImpl implements CharEscape {

        @Override
        public String charEscape(String charString) {
            if (!StringUtils.hasLength(charString)) {
                return charString;
            }
            charString = charString.trim();
            if (charString.contains("\\")) {
                charString = charString.replaceAll("\\\\", "\\\\");
            }
            if (charString.contains("%")) {
                charString = charString.replaceAll("%", "\\\\%");
            }
            if (charString.contains("_")) {
                charString = charString.replaceAll("_", "\\\\_");
            }
            return charString;
        }
    }
}


2. 实现字符转义类

默认是CharEscapeImpl ()这个类中方法进行字符转义,也可以自定义实现类进行字符转义

public class TestCharEscape implements CharEscapeInnerInterceptor.CharEscape {
    @Override
    public String charEscape(String charString) {
        // 实现转义
        return "1";
    }
}

3. 修改mybatis配置 ,添加拦截器

CharEscapeInnerInterceptor有两个构造方法
在这里插入图片描述

3.1 无参

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        interceptor.addInnerInterceptor(new CharEscapeInnerInterceptor());
        return interceptor;
    }
}

3.2 自定义转义实现类

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        interceptor.addInnerInterceptor(new CharEscapeInnerInterceptor(new TestCharEscape ()));
        return interceptor;
    }
}

4. 测试

在这里插入图片描述
在这里插入图片描述
结果:传入参数为%,查询时sql参数为\%参数已转义

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值