当前位置: 首页 > news >正文

MyBatis学习笔记-参数转义处理

查询参数中如果有传入%的情况,数据会被全量返回。类似的可能还会有一些特殊符号的情况存在。这个时候可能需要在查询数据的时候进行参数转义处理。一般情况可能会考虑选择下面的两种方式处理。
一、基于Filter处理
主要通过实现Filter接口,自定义HttpServletRequestWrapper处理参数数据。
  • 注意事项
    • 全局参数的一个统一拦截替换。不是能很好的区分增删改查,进行更细粒度的控制。
二、基于Interceptor处理
主要通过实现Interceptor接口,自定义处理查询操作的参数数据。
  • 注意事项
    • 可以支持仅处理查询操作的参数。
    • 参数的类型会比较多,需要根据不同的参数类型进行单独的处理。
@Slf4j
@AllArgsConstructor
@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class)})
public class ParameterEscapeInterceptor implements Interceptor {private static final Pattern EW_SQL_PATTERN = Pattern.compile("\\w+\\s\\S+\\s#\\{ew.paramNameValuePairs.MPGENVAL\\d+}");private static final Pattern EW_MPG_PATTERN = Pattern.compile("MPGENVAL\\d+");private final ParameterEscapeProperties parameterEscapeProperties;@Overridepublic Object intercept(Invocation invocation) throws Throwable {ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();// MetaObject是MyBatis提供的一个反射帮助类,可以优雅访问对象的属性,这里是对parameterHandler对象进行反射处理,MetaObject metaObject = MetaObject.forObject(parameterHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());if (!"SELECT".equalsIgnoreCase(String.valueOf(metaObject.getValue("sqlCommandType")))) {return invocation.proceed();}Object parameterObject = parameterHandler.getParameterObject();if (null == parameterObject) {return invocation.proceed();}if (parameterObject instanceof Map) {Map<String, Object> parameterMapObject = (Map<String, Object>) parameterObject;if (parameterMapObject.containsKey(com.baomidou.mybatisplus.core.toolkit.Constants.ENTITY)) {// handle entity objectObject etObject = parameterMapObject.get(com.baomidou.mybatisplus.core.toolkit.Constants.ENTITY);if (null != etObject) {handleObjectFields(etObject);}} if (parameterMapObject.containsKey(com.baomidou.mybatisplus.core.toolkit.Constants.WRAPPER)) {// handle wrapper objecthandleWrapperObjectFields(metaObject);} else {// handle map objecthandleMapObjectFields(parameterMapObject);}} else {handleObjectFields(parameterObject);}return invocation.proceed();}// handle wrapper objectprivate void handleWrapperObjectFields(MetaObject metaObject) {Object paramNameValuePairs = metaObject.getValue("parameterObject.ew.paramNameValuePairs");if (null == paramNameValuePairs) {return;}if (paramNameValuePairs instanceof Map) {Map<String, String> mpgFieldConditionMap = new HashMap<>();Matcher ewSqlMatcher = EW_SQL_PATTERN.matcher(String.valueOf(metaObject.getValue("parameterObject.ew.expression.sqlSegment")));while (ewSqlMatcher.find()) {String[] conditionKV = ewSqlMatcher.group().split("\\s");if (null != conditionKV && conditionKV.length > 1) {Matcher mpgMatcher = EW_MPG_PATTERN.matcher(conditionKV[2]);if (mpgMatcher.find()) {mpgFieldConditionMap.put(mpgMatcher.group(), conditionKV[1]);}}}Map<String, Object> paramNameValuePairsMap = (Map) paramNameValuePairs;for (Map.Entry<String, Object> entry : paramNameValuePairsMap.entrySet()) {String paramName = entry.getKey();paramNameValuePairsMap.put(paramName, handleObjectField(entry.getValue(), mpgFieldConditionMap.get(paramName)));}}}// handle map objectprivate void handleMapObjectFields(Map<String, Object> parameterObject) {for (Map.Entry<String, Object> entry : parameterObject.entrySet()) {try {Object fieldValue = entry.getValue();if (ObjectUtil.isNull(fieldValue)) {continue;}if (fieldValue instanceof Map) {handleMapObjectFields((Map) fieldValue);}parameterObject.put(entry.getKey(), handleObjectField(fieldValue));} catch (Exception e) {log.info(e.getMessage());}}}private void handleObjectFields(Object object) {Field[] declaredFields = object.getClass().getDeclaredFields();for (int i = 0, len = declaredFields.length; i < len; i++) {Field declaredField = declaredFields[i];if (Modifier.isStatic(declaredField.getModifiers())) {continue;}String declaredFieldName = declaredField.getName();if ("serialVersionUID".equalsIgnoreCase(declaredFieldName) || "handler".equalsIgnoreCase(declaredFieldName)) {continue;}declaredField.setAccessible(true);try {Object declaredFieldValue = declaredField.get(object);if (ObjectUtil.isNull(declaredFieldValue)) {continue;}declaredField.set(object, handleObjectField(declaredFieldValue));} catch (Exception e) {log.info(e.getMessage());}declaredField.setAccessible(false);}}private Object handleObjectField(Object objectFieldValue) {return handleObjectField(objectFieldValue, null);}private Object handleObjectField(Object objectFieldValue, String condition) {if (ObjectUtil.isNotEmpty(objectFieldValue) && objectFieldValue instanceof String) {String objectFieldStringValue = String.valueOf(objectFieldValue);String prefix = "";String suffix = "";boolean isLikeCondition = "LIKE".equalsIgnoreCase(condition) && objectFieldStringValue.length() >= 2;if (isLikeCondition) {if (objectFieldStringValue.startsWith("%")) {prefix = "%";objectFieldStringValue = objectFieldStringValue.substring(1);}if (objectFieldStringValue.endsWith("%")) {suffix = "%";objectFieldStringValue = objectFieldStringValue.substring(0, objectFieldStringValue.length() - 1);}}for (Map.Entry<String, String> entry : parameterEscapeProperties.getEscapeMapping().entrySet()) {objectFieldStringValue = objectFieldStringValue.replaceAll(entry.getKey(), entry.getValue());}return isLikeCondition ? prefix + objectFieldStringValue + suffix : objectFieldStringValue;}return objectFieldValue;}}

总的来说,参数转义的处理还是比较简单的,也可以比较灵活。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • App UI性能测试 - PerfDog使用全教程
  • 如何实现一套键盘鼠标控制两台计算机(Mouse Without Borders快速上手教程)
  • Docker搭建MySQL双主复制详细教程
  • 【前端】从零开始学习编写HTML
  • HNU小学期BSP软件编程基础十道测试题
  • Java学习
  • Linux基础IO
  • 海外金融机构银行保险证券数字化转型营销销售数字化成功案例讲师培训师讲授开户销售营销客户AI人工智能创新思维
  • 红酒知识百科:从入门到精通
  • 入门PHP就来我这(高级)18 ~ 获取结果集
  • 【C++】开源:坐标转换和大地测量GeographicLib库配置使用
  • 【Java算法】二分查找 下
  • 大模型学习笔记0-前言
  • vue 切换主题色切换主题色切换主题色切换主题色切换主题色
  • python使用tkinter添加下载进度UI
  • 07.Android之多媒体问题
  • Apache Pulsar 2.1 重磅发布
  • DOM的那些事
  • Flannel解读
  • js
  • js递归,无限分级树形折叠菜单
  • js作用域和this的理解
  • mongo索引构建
  • spring security oauth2 password授权模式
  • Web Storage相关
  • 如何胜任知名企业的商业数据分析师?
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 思维导图—你不知道的JavaScript中卷
  • 算法之不定期更新(一)(2018-04-12)
  • 微信小程序:实现悬浮返回和分享按钮
  • 我与Jetbrains的这些年
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 走向全栈之MongoDB的使用
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • $(function(){})与(function($){....})(jQuery)的区别
  • (2024,Flag-DiT,文本引导的多模态生成,SR,统一的标记化,RoPE、RMSNorm 和流匹配)Lumina-T2X
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (一)appium-desktop定位元素原理
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)树状数组
  • (转)项目管理杂谈-我所期望的新人
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .gitignore文件_Git:.gitignore
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Core 中插件式开发实现
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET/C#⾯试题汇总系列:⾯向对象
  • .NET关于 跳过SSL中遇到的问题
  • @data注解_一枚 架构师 也不会用的Lombok注解,相见恨晚
  • @SpringBootApplication 注解