mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现方法是什么
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容主要讲解"mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"my
千家信息网最后更新 2026年11月01日mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现方法是什么1.使用mybatis提供的拦截器拦截所有的查询请求。
2.定义SQL语句转义模板,分别对Map和Object对象进行处理
本篇内容主要讲解"mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现方法是什么"吧!
1.使用mybatis提供的拦截器拦截所有的查询请求。
具体实现在代码中均有注释
import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import java.util.*;/** * mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器 * * @author lieber */@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})@Slf4jpublic class MybatisLikeSqlInterceptor implements Interceptor { /** * SQL语句like */ private final static String SQL_LIKE = " like "; /** * SQL语句占位符 */ private final static String SQL_PLACEHOLDER = "?"; /** * SQL语句占位符分隔 */ private final static String SQL_PLACEHOLDER_REGEX = "\\?"; /** * 所有的转义器 */ private static Map converterMap = new HashMap<>(4); static { converterMap.put(Map.class, new MapLikeSqlConverter()); converterMap.put(Object.class, new ObjectLikeSqlConverter()); } @Override public Object intercept(Invocation invocation) throws Throwable { Object[] args = invocation.getArgs(); MappedStatement statement = (MappedStatement) args[0]; Object parameterObject = args[1]; BoundSql boundSql = statement.getBoundSql(parameterObject); String sql = boundSql.getSql(); this.transferLikeSql(sql, parameterObject, boundSql); return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties arg0) { } /** * 修改包含like的SQL语句 * * @param sql SQL语句 * @param parameterObject 参数对象 * @param boundSql 绑定SQL对象 */ private void transferLikeSql(String sql, Object parameterObject, BoundSql boundSql) { if (!isEscape(sql)) { return; } sql = sql.replaceAll(" {2}", " "); // 获取关键字的个数(去重) Set fields = this.getKeyFields(sql, boundSql); if (fields == null) { return; } // 此处可以增强,不止是支持Map对象,Map对象仅用于传入的条件为Map或者使用@Param传入的对象被Mybatis转为的Map AbstractLikeSqlConverter converter; // 对关键字进行特殊字符"清洗",如果有特殊字符的,在特殊字符前添加转义字符(\) if (parameterObject instanceof Map) { converter = converterMap.get(Map.class); } else { converter = converterMap.get(Object.class); } converter.convert(sql, fields, parameterObject); } /** * 是否需要转义 * * @param sql SQL语句 * @return true/false */ private boolean isEscape(String sql) { return this.hasLike(sql) && this.hasPlaceholder(sql); } /** * 判断SQL语句中是否含有like关键字 * * @param str SQL语句 * @return true/false */ private boolean hasLike(String str) { if (StringUtils.isBlank(str)) { return false; } return str.toLowerCase().contains(SQL_LIKE); } /** * 判断SQL语句中是否包含SQL占位符 * * @param str SQL语句 * @return true/false */ private boolean hasPlaceholder(String str) { if (StringUtils.isBlank(str)) { return false; } return str.toLowerCase().contains(SQL_PLACEHOLDER); } /** * 获取需要替换的所有字段集合 * * @param sql 完整SQL语句 * @param boundSql 绑定的SQL对象 * @return 字段集合列表 */ private Set getKeyFields(String sql, BoundSql boundSql) { String[] params = sql.split(SQL_PLACEHOLDER_REGEX); Set fields = new HashSet<>(); for (int i = 0; i < params.length; i++) { if (this.hasLike(params[i])) { String field = boundSql.getParameterMappings().get(i).getProperty(); fields.add(field); } } return fields; }} 2.定义SQL语句转义模板,分别对Map和Object对象进行处理
2.1 定义AbstractLikeSqlConverter
import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import java.beans.IntrospectionException;import java.beans.PropertyDescriptor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Set;/** * 包含like的SQL语句转义模板 * * @author lieber */@Slf4jpublic abstract class AbstractLikeSqlConverter{ /** * SQL语句like使用关键字% */ private final static String LIKE_SQL_KEY = "%"; /** * SQL语句需要转义的关键字 */ private final static String[] ESCAPE_CHAR = new String[]{LIKE_SQL_KEY, "_", "\\"}; /** * mybatis-plus中like的SQL语句样式 */ private final static String MYBATIS_PLUS_LIKE_SQL = " like ?"; /** * mybatis-plus中参数前缀 */ private final static String MYBATIS_PLUS_WRAPPER_PREFIX = "ew.paramNameValuePairs."; /** * mybatis-plus中参数键 */ final static String MYBATIS_PLUS_WRAPPER_KEY = "ew"; /** * mybatis-plus中参数分隔符 */ final static String MYBATIS_PLUS_WRAPPER_SEPARATOR = "."; /** * mybatis-plus中参数分隔符替换器 */ final static String MYBATIS_PLUS_WRAPPER_SEPARATOR_REGEX = "\\."; /** * 已经替换过的标记 */ final static String REPLACED_LIKE_KEYWORD_MARK = "replaced.keyword"; /** * 转义特殊字符 * * @param sql SQL语句 * @param fields 字段列表 * @param parameter 参数对象 */ public void convert(String sql, Set fields, T parameter) { for (String field : fields) { if (this.hasMybatisPlusLikeSql(sql)) { if (this.hasWrapper(field)) { // 第一种情况:在业务层进行条件构造产生的模糊查询关键字,使用QueryWrapper,LambdaQueryWrapper this.transferWrapper(field, parameter); } else { // 第二种情况:未使用条件构造器,但是在service层进行了查询关键字与模糊查询符`%`手动拼接 this.transferSelf(field, parameter); } } else { // 第三种情况:在Mapper类的注解SQL中进行了模糊查询的拼接 this.transferSplice(field, parameter); } } } /** * 转义条件构造的特殊字符 * 在业务层进行条件构造产生的模糊查询关键字,使用QueryWrapper,LambdaQueryWrapper * * @param field 字段名称 * @param parameter 参数对象 */ public abstract void transferWrapper(String field, T parameter); /** * 转义自定义条件拼接的特殊字符 * 未使用条件构造器,但是在service层进行了查询关键字与模糊查询符`%`手动拼接 * * @param field 字段名称 * @param parameter 参数对象 */ public abstract void transferSelf(String field, T parameter); /** * 转义自定义条件拼接的特殊字符 * 在Mapper类的注解SQL中进行了模糊查询的拼接 * * @param field 字段名称 * @param parameter 参数对象 */ public abstract void transferSplice(String field, T parameter); /** * 转义通配符 * * @param before 待转义字符串 * @return 转义后字符串 */ String escapeChar(String before) { if (StringUtils.isNotBlank(before)) { before = before.replaceAll("\\\\", "\\\\\\\\"); before = before.replaceAll("_", "\\\\_"); before = before.replaceAll("%", "\\\\%"); } return before; } /** * 是否包含需要转义的字符 * * @param obj 待判断的对象 * @return true/false */ boolean hasEscapeChar(Object obj) { if (!(obj instanceof String)) { return false; } return this.hasEscapeChar((String) obj); } /** * 处理对象like问题 * * @param field 对象字段 * @param parameter 对象 */ void resolveObj(String field, Object parameter) { if (parameter == null || StringUtils.isBlank(field)) { return; } try { PropertyDescriptor descriptor = new PropertyDescriptor(field, parameter.getClass()); Method readMethod = descriptor.getReadMethod(); Object param = readMethod.invoke(parameter); if (this.hasEscapeChar(param)) { Method setMethod = descriptor.getWriteMethod(); setMethod.invoke(parameter, this.escapeChar(param.toString())); } else if (this.cascade(field)) { int index = field.indexOf(MYBATIS_PLUS_WRAPPER_SEPARATOR) + 1; this.resolveObj(field.substring(index), param); } } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) { log.error("反射 {} 的 {} get/set方法出现异常", parameter, field, e); } } /** * 判断是否是级联属性 * * @param field 字段名 * @return true/false */ boolean cascade(String field) { if (StringUtils.isBlank(field)) { return false; } return field.contains(MYBATIS_PLUS_WRAPPER_SEPARATOR) && !this.hasWrapper(field); } /** * 是否包含mybatis-plus的包含like的SQL语句格式 * * @param sql 完整SQL语句 * @return true/false */ private boolean hasMybatisPlusLikeSql(String sql) { if (StringUtils.isBlank(sql)) { return false; } return sql.toLowerCase().contains(MYBATIS_PLUS_LIKE_SQL); } /** * 判断是否使用mybatis-plus条件构造器 * * @param field 字段 * @return true/false */ private boolean hasWrapper(String field) { if (StringUtils.isBlank(field)) { return false; } return field.contains(MYBATIS_PLUS_WRAPPER_PREFIX); } /** * 判断字符串是否含有需要转义的字符 * * @param str 待判断的字符串 * @return true/false */ private boolean hasEscapeChar(String str) { if (StringUtils.isBlank(str)) { return false; } for (String s : ESCAPE_CHAR) { if (str.contains(s)) { return true; } } return false; }}
2.2 定义MapLikeSqlConverter处理Map类型参数的情况
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;import java.util.Map;import java.util.Objects;/** * 参数对象为Map的转换器 * * @author lieber * @create_date 2020/1/21 12:28 */public class MapLikeSqlConverter extends AbstractLikeSqlConverter
2.3 定义ObjectLikeSqlConverter处理Object类型参数的情况
import lombok.extern.slf4j.Slf4j;/** * 通用参数的转换器 * * @author lieber */@Slf4jpublic class ObjectLikeSqlConverter extends AbstractLikeSqlConverter
3. 注册到Spring中
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * mybatis/mybatis-plus模糊查询语句特殊字符转义配置 * * @author lieber */@Configurationpublic class MybatisLikeSqlConfig { @Bean public MybatisLikeSqlInterceptor mybatisSqlInterceptor() { return new MybatisLikeSqlInterceptor(); }}到此,即可进行关键字的精确匹配。
到此,相信大家对"mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现方法是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
语句
字符
转义
对象
查询
参数
特殊
关键
关键字
字段
条件
情况
方法
拦截器
字符串
处理
名称
构造器
业务
内容
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
咖啡网
互联网科技公司排名
亿人帮互联网科技有限公司
新华互联网科技学院
北京互联网科技
狮子座互联网科技
小马过河互联网科技
金融科技和互联网金融
美国互联网前沿科技
互联网科技生活的内容
海南科技产业互联网平台
昭通云南众福互联网科技有限公司
湖南一路畅行互联网科技
亳州好赞互联网科技有限公司
济南有互联网科技公司吗
国大互联网教育科技有限公司薪资
宇信科技在杭州互联网排第几
互联网与数字科技关系
科技互联网经济论坛
高科技和互联网的现代国家
北京互联网科技有限公司
易互联网科技有限公司
高科技与互联网
智网互联网科技
朗涯互联网科技
善班互联网科技有限公司
深圳前海聚择互联网科技有限公司
成都铂石互联网科技做什么的
互联网科技的全部知识
互联网科技融合创新