解決SpringMVC使用MyBatis-Plus自定義MyBaits攔截器不生效的問題

自定義MyBatis攔截器

如果是SpringBoot項目引入@Component注解就生效了,但是SpringMVC不行

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.util.StringUtils;import java.lang.reflect.Field;
import java.sql.Statement;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "update", args = {Statement.class,}),@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class})
})
//@Component 在SpringBoot生效,在SpringMVC不生效
public final class MyBatisSqlParsingPlugin implements Interceptor {private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();ParameterHandler parameterHandler = statementHandler.getParameterHandler();BoundSql boundSql = statementHandler.getBoundSql();try {String sql = formatSql(parameterHandler, boundSql);if (!boundSql.getSql().equals(sql)) {log.info("Execute SQL:{}", sql);}} catch (Exception e) {String sql = boundSql.getSql();log.error("Execute SQL:{}\nException:", sql, e);}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Interceptor.super.plugin(target);}@Overridepublic void setProperties(Properties properties) {Interceptor.super.setProperties(properties);}/*** 格式化SQL及其參數*/private String formatSql(ParameterHandler parameterHandler, BoundSql boundSql) throws NoSuchFieldException, IllegalAccessException {Class<? extends ParameterHandler> parameterHandlerClass = parameterHandler.getClass();Field mappedStatementField = parameterHandlerClass.getDeclaredField("mappedStatement");mappedStatementField.setAccessible(true);MappedStatement mappedStatement = (MappedStatement) mappedStatementField.get(parameterHandler);String sql = boundSql.getSql().replaceAll("\\s+", " ");// sql字符串是空或存儲過程,直接跳過if (!StringUtils.hasText(sql) || sql.trim().charAt(0) == '{') {return "";}// 不傳參數的場景,直接把Sql美化一下返回出去Object parameterObject = parameterHandler.getParameterObject();List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();if (Objects.isNull(parameterObject) || parameterMappingList.isEmpty()) {return sql;}return handleCommonParameter(sql, boundSql, mappedStatement);}//替換預編譯SQLprivate String handleCommonParameter(String sql, BoundSql boundSql, MappedStatement mappedStatement) {Object parameterObject = boundSql.getParameterObject();List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();Configuration configuration = mappedStatement.getConfiguration();TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();List<String> params = new ArrayList<>();for (ParameterMapping parameterMapping : parameterMappings) {if (parameterMapping.getMode() == ParameterMode.OUT) {continue;}Object propertyValue;String propertyName = parameterMapping.getProperty();if (boundSql.hasAdditionalParameter(propertyName)) {propertyValue = boundSql.getAdditionalParameter(propertyName);} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {propertyValue = parameterObject;} else {MetaObject metaObject = configuration.newMetaObject(parameterObject);propertyValue = metaObject.getValue(propertyName);}params.add(this.formatParam(propertyValue));}//轉譯百分號if (sql.contains("%")) {//如果參數不一致直接返回SQLPattern pattern = Pattern.compile("\\?");Matcher matcher = pattern.matcher(sql);int count = 0;while (matcher.find()) {count++;}if (count == 0 || params.isEmpty()) {return sql;}if (params.size() != count) {log.error("SQL:{}", sql);log.error("SQL parameters:{}", params);return sql;}sql = sql.replaceAll("%", "%%");}sql = sql.replaceAll("\\?", "%s");return String.format(sql, params.toArray());}private String formatParam(Object object) {if (object == null) {return "null";}if (object instanceof String) {return formatString((String) object);}if (object instanceof Date) {return formatDate((Date) object);}if (object instanceof LocalDate) {return formatLocalDate((LocalDate) object);}if (object instanceof LocalDateTime) {return formatLocalDateTime((LocalDateTime) object);}return object.toString();}private static String formatString(String str) {return "'" + str + "'";}private String formatDate(Date date) {return "'" + DATE_TIME_FORMATTER.format(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()) + "'";}private String formatLocalDate(LocalDate date) {return "'" + DATE_FORMATTER.format(date) + "'";}private String formatLocalDateTime(LocalDateTime dateTime) {return "'" + DATE_TIME_FORMATTER.format(dateTime) + "'";}
}

mybatis-plus使用mybatis插件

MybatisPlusInterceptor實現的是MyBaits Interceptor接口,而MybatisPlusInterceptor自己又創建了一個InnerInterceptor接口去實現自己的插件,比如:PaginationInnerInterceptor 分頁插件。我們使用的是MyBatis Interceptor的插件,所以不能注入到MybatisPlusInterceptor類里面,而是要和MybatisPlusInterceptor平級,因為前面也說了MybatisPlusInterceptor 實現的是MyBaits Interceptor,而我們自定義的MyBatisSqlParsingPlugin實現的也是MyBaits Interceptor,因此要和MybatisPlusInterceptor平級放到plugins下面,建議自定義的MyBaits Interceptor要放到MybatisPlusInterceptor前面,防止MybatisPlusInterceptor干擾我們自定義的插件。

	<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="mapperLocations" value="classpath*:mapper/**/*.xml"/><property name="typeAliasesPackage" value="com.bsoft.extend.mybatis.entity"/><property name="plugins"><array><!-- 引入的是 MyBatis 插件 --><ref bean="myBatisSqlParsingPlugin"/><!-- 引入的是 MyBatis-Plus 自己封裝的插件 --><ref bean="mybatisPlusInterceptor"/></array></property></bean><!-- 實現 MyBatis Interceptor 接口的插件 --><bean id="myBatisSqlParsingPlugin" class="com.bsoft.extend.mybatis.plugins.MyBatisSqlParsingPlugin"/><!-- 實現 MyBatis-Plus InnerInterceptor 接口的插件【就是MyBatis-Plus自己封裝的插件】 --><bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor"><property name="interceptors"><list><!-- 引入 MyBatis-Plus 分頁插件 --><ref bean="paginationInnerInterceptor"/></list></property></bean><!-- MyBatis-Plus 分頁插件配置 --><bean id="paginationInnerInterceptor" class="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor"><constructor-arg name="dbType" value="ORACLE"/><property name="optimizeJoin" value="true"/></bean>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/35271.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/35271.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/35271.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

亮數據,一款新的低代碼爬蟲利器!

在當今數據驅動型時代&#xff0c;數據采集和分析能力算是個人和企業的核心競爭力。然而&#xff0c;手動采集數據耗時費力且效率低下&#xff0c;而且容易被網站封禁。 我之前使用過一個爬蟲工具&#xff0c;亮數據&#xff08;Bright Data&#xff09; &#xff0c;是一款低…

力扣隨機一題 哈希表 排序 數組

博客主頁&#xff1a;誓則盟約系列專欄&#xff1a;IT競賽 專欄關注博主&#xff0c;后期持續更新系列文章如果有錯誤感謝請大家批評指出&#xff0c;及時修改感謝大家點贊&#x1f44d;收藏?評論? 2491.劃分技能點相等的團隊【中等】 題目&#xff1a; 給你一個正整數數組…

【深海王國】小學生都能玩的單片機?零基礎入門單片機Arduino帶你打開嵌入式的大門!(9)

Hi?(?o?)?, 各位深海王國的同志們&#xff0c;早上下午晚上凌晨好呀~辛勤工作的你今天也辛苦啦 (o゜▽゜)o☆ 今天大都督繼續為大家帶來系列——小學生都能玩的單片機&#xff01;帶你一周內快速走進嵌入式的大門&#xff0c;let’s go&#xff01; &#xff08;9&#x…

殷山:摩斯大模型隱私保護技術和應用探索

背景介紹 6月20日下午&#xff0c;“2024信通院數據智能大會”圓滿落幕&#xff0c;摩斯技術負責人殷山在論壇上分享了摩斯在大模型隱私保護技術和行業應用的探索。 殷山發表“大模型隱私保護”主題演講 摩斯技術負責人殷山在“數據智能安全主題論壇“上&#xff0c;帶來“大…

web學習筆記(六十八)項目總結

目錄 1.如何取到對象的第一項的鍵名 2.如何在鍵名不確定的情況下取到對象的第一項的值 3.如何獲取對象的長度 4.計算屬性和watch監聽監聽深層數據 5.樣式穿透 1.如何取到對象的第一項的鍵名 可以通過Object.keys將對象轉化為一個包含對象所有可枚舉屬性名的數組&#xff…

Java中的微服務架構實現方法

Java中的微服務架構實現方法 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 在當今軟件開發的環境中&#xff0c;微服務架構已經成為了構建大型應用程序的主流…

NIVision-LabVIEW在灰度圖上畫圓

問題來源 在csdn上看到的這樣一個問題&#xff0c;好像也沒個正經答案&#xff0c;都用chatGPT回答&#xff0c;挺沒勁的。不說提供個vi源代碼&#xff0c;至少也來張截圖嘛。我想著問題也不難&#xff0c;就自己動動手吧。 代碼展示1 1、首先使用imaq ArrayToImage.vi創建了一…

java error ConcurrentModificationException 并發修改異常

ConcurrentModificationException 概述 這個異常在 Java 中通常發生在以下場景&#xff1a;當某個線程在遍歷一個集合&#xff08;如 ArrayList、HashMap 等&#xff09;的過程中&#xff0c;另一個線程嘗試修改這個集合的結構&#xff08;如添加、刪除元素&#xff09;&#…

java中處理RunTimeException類的方式

在Java中&#xff0c;RuntimeException是所有運行時異常的父類。一些常見的RuntimeException子類包括&#xff1a; NullPointerException&#xff08;空指針異常&#xff09;&#xff1a;當試圖訪問空對象的屬性或調用空對象的方法時拋出。IllegalArgumentException&#xff0…

sheng的學習筆記-AI-學習向量量化

AI目錄 sheng的學習筆記-AI目錄-CSDN博客 需要學習前置知識&#xff1a;聚類&#xff0c;可參考 sheng的學習筆記-AI-聚類(Clustering)-CSDN博客 什么是學習向量量化 “學習向量量化”&#xff08;Learning Vector Quantization&#xff0c;簡稱LVQ&#xff09;是試圖找到一…

【Android面試八股文】ViewHolder為什么要被聲明成靜態內部類?

文章目錄 ViewHolder為什么要被聲明成靜態內部類?1. 避免隱式引用導致的內存泄漏2. 提高性能3. 代碼可讀性和維護性實例代碼總結ViewHolder為什么要被聲明成靜態內部類? 將 ViewHolder 聲明為靜態內部類有幾個重要的原因,這樣做可以提高性能并避免潛在的內存泄漏。下面是詳…

Qt | 子類化 QStyle(Qt自帶圖標大全)

01、簡介 1、把繪制自定義部件外觀的步驟大致分為三大板塊,如下: ①、樣式元素:即指定需要繪制的圖形元素(比如焦點框、按鈕,工具欄等)。樣式元素使 用 QStyle 類中的一系列枚舉(共有 11 個枚舉)進行描述。 ②、樣式選項:包含了需要繪制的圖形元素的所有信息,比如包含…

Tomcat 下載部署到 idea

一、下載Tomcat Tomcat 是Apache 軟件基金會&#xff08;Apache Software Foundation&#xff09;下的一個核心項目&#xff0c;免費開源、并支持Servlet 和JSP 規范。屬于輕量級應用服務器&#xff0c;在中小型系統和并發訪問用戶不是很多的場合下被普遍使用&#xff0c;是開發…

啟動VMWare虛擬機報錯

1. 無法打開內核設備“\\.\VMCIDev\VMX”: 操作成功完成。是否在安裝 VMware Workstation 后重新引導? 模塊“DevicePowerOn”啟動失敗。 未能啟動虛擬機。 解決辦法: 解決辦法: 將 Ubuntu 64 位.vmx 找到vmci0.present"TRUE"這行改成 vmci0.present "FAL…

wireshark工具獲取設備IP地址

背景&#xff1a; 一個網口抓包工具&#xff0c;主要是升級XX設備時候不知道網口的ip地址。每次需要一個一個試&#xff0c;比較麻煩。 使用步驟&#xff1a; 1、連接好XX設備與筆記本&#xff0c;在網絡連接里面找到以太網&#xff0c;沒有出現紅色X號&#xff0c;表示網線連…

文心一言 VS 訊飛星火 VS chatgpt (289)-- 算法導論21.3 2題

二、寫出使用路徑壓縮的 FIND-SET 過程的非遞歸版本。如果要寫代碼&#xff0c;請用go語言。 文心一言&#xff1a; 在并查集&#xff08;Union-Find&#xff09;數據結構中&#xff0c;路徑壓縮&#xff08;Path Compression&#xff09;是一種優化技術&#xff0c;用于減少…

智能倉儲:立體倉WCS設計

自動化立體倉庫簡稱高架倉庫&#xff0c;是采用高層貨架存放貨物&#xff0c;以巷道堆垛起重機為主&#xff0c;結合入庫出庫周邊設備來進行作業的一種倉庫。 立體倉主體由貨架、巷道式堆垛機、輸送機等組成。 電氣控制系統、上位監控系統&#xff08;Warehouse Control Syste…

【前后端實現】AHP權重計算

AHP權重計算&#xff1a; 需求&#xff1a;前端記錄矩陣維度、上三角值&#xff0c;后端構建比較矩陣、計算權重值并將結果返回給前端 比較矩陣構建 如果你想要根據上三角&#xff08;不包括對角線&#xff09;的值來構建對稱矩陣&#xff0c;那么你可以稍作修改上述的generate…

.NET 語言特定指南

.NET Language-Specific Guide 本指南將教您如何使用 Docker 創建容器化的 .NET 應用程序。通過本指南&#xff0c;您將學習如何&#xff1a; 容器化并運行 .NET 應用程序設置本地環境以使用容器開發 .NET 應用程序使用容器運行 .NET 應用程序測試使用 GitHub Actions 配置容…

量化交易面臨的難題

量化交易面臨的難題 1、監管機構對于算法交易、量化交易的監管越來越嚴格3、回測場景于實盤交易場景的不匹配性4、策略并非100%有效&#xff0c;并非100%的收益5、股票、基本面、市場新聞之間的關系時刻在變化并且難以捉摸6、很難使用一套通用的交易規則去匹配所有的股票/市場/…