中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

mybatis攔截器怎么使用

發布時間:2023-03-21 14:50:03 來源:億速云 閱讀:78 作者:iii 欄目:開發技術

今天小編給大家分享一下mybatis攔截器怎么使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    mybatis實戰之攔截器

    在服務的開發過程中,往往存在這樣的需求,針對業務,實現對數據庫操作語句做統一的處理。

    比如對某些敏感數據如用戶姓名、手機號等坐脫敏處理保存和查詢、對未實現權限的查詢通過添加關聯查詢實現權限控制查詢結果等等。

    這時,mybatis框架提供了攔截器的方式,允許在映射語句執行過程中的某一點進行攔截調用,進行自己的業務處理。

    1、使用方法

    這里參考了官網的使用說明,只需實現 Interceptor 接口,并在類中指定想要攔截的方法簽名即可。

    比如:

    @Intercepts({@Signature(
      type= Executor.class,
      method = "update",
      args = {MappedStatement.class,Object.class})})
    public class ExamplePlugin implements Interceptor {
      private Properties properties = new Properties();
      public Object intercept(Invocation invocation) throws Throwable {
        // implement pre processing if need
        Object returnObject = invocation.proceed();
        // implement post processing if need
        return returnObject;
      }
      public void setProperties(Properties properties) {
        this.properties = properties;
      }
    }

    然后在mybatis的配置文件中,添加插件的對應配置即可。

    <!-- mybatis-config.xml -->
    <plugins>
      <plugin interceptor="org.mybatis.example.ExamplePlugin">
        <property name="someProperty" value="100"/>
      </plugin>
    </plugins>

    我們也可以在代碼中添加,下面給出在spring中

    //通過spring查找SqlSessionFactory對象的邏輯在此省略
    SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) var3;
    org.apache.ibatis.session.Configuration c = sqlSessionFactory.getConfiguration();
    c.addInterceptor(interceptor);

    分別加上處理的業務邏輯,這個攔截器就可以使用了。

    2、需要注意的地方

    第一節簡單介紹了,攔截器的使用方法,但在實際項目中這樣還遠遠不夠。

    筆者在本節列舉了一些需要注意的地方,供大家思考討論。

    攔截器的執行順序

    攔截器的調用順序分為兩大種,第一種是攔截的不同對象,第二種是指攔截同一種對象的同一個方法。

    第一種情況,例如攔截 Executor 和 攔截 StatementHandler 就屬于不同的攔截對象, 這兩類的攔截器在整體執行的邏輯上是不同的。

    StatementHandler 屬于 Executor 執行過程中的一個子過程。

    所以這兩種不同類別的插件在配置時,一定是先執行 Executor 的攔截器,然后才會輪到 StatementHandler。

    所以這種情況下配置攔截器的順序就不重要了,在 MyBatis 邏輯上就已經控制了先后順序。

    第二種情況,例如都攔截 Executor 的 query 方法,這時你配置攔截器的順序就會對這里有影響了。比如配置如下。

    <plugins>
        <plugin interceptor="com.github.pagehelper.ExecutorQueryInterceptor1"/>
        <plugin interceptor="com.github.pagehelper.ExecutorQueryInterceptor2"/>
        <plugin interceptor="com.github.pagehelper.ExecutorQueryInterceptor3"/>
    </plugins>

    前面我們配置攔截器的順序是1,2,3。在這里也會按照 1,2,3 的順序被層層代理,代理后的結構如下:

    Interceptor3:{
        Interceptor2: {
            Interceptor1: {
                target: Executor
            }
        }
    }

    然后到執行的邏輯:

    Interceptor3 前置處理
    Interceptor2 前置處理
    Interceptor1 前置處理  
    Object result = executor.query(4個參數方法);     
    Interceptor1 后續處理   
    Interceptor2 后續處理  
    Interceptor3 后續處理   
    return result;

    順序就是 3>2>1>Executor>1>2>3。MyBatis的攔截器采用責任鏈設計模式,多個攔截器之間的責任鏈是通過動態代理組織的。

    我們一般都會在攔截器中的intercept方法中往往會有invocation.proceed()語句,其作用是將攔截器責任鏈向后傳遞,本質上便是動態代理的invoke。

    與常用插件的整合遇到的問題

    pageHelper造成分頁失效的問題

    通過查看pagehelper源碼,可以看到其inercept方法直接獲取了excutor然后開始分頁查詢,當查詢到結果時,便返回了。

    就是pagehelper的intercept方法中沒有invocation.proceed(),這意味著什么?

    //com.github.pagehelper.PageInterceptor#intercept
    .....
                    resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
                }
                return dialect.afterPage(resultList, parameter, rowBounds);
            } finally {
                dialect.afterAll();
            }

    這意味著pagehelper沒有繼續向后傳遞責任鏈,而是自行處理直接返回。

    由此,我們可以猜出該問題大概率與攔截器的執行順序有關。

    通過斷點調試,驗證了該猜想,當遇到分頁查詢時,執行到pagehelper就結束了,沒有進入我們的自定義攔截器。這就可能造成我們自定義攔截器失效。

    解決方案

    因為PageHelper是Excetor類型的攔截器,所以我們如果想要在PageHelper攔截器前面執行,就必須要將我們自己的攔截器添加到他的攔截器后面。

    這里只介紹最簡單最優雅的一種方式:

    注冊一個ApplicationListener監聽器,監聽 ContextRefreshedEvent 事件,當所有的bean都初始化完成后(即PageHelper也已經注冊好了),再把我們的自定義 MyBatis 攔截器注冊到 SqlSessionFactory 中。

    可以提升的點

    Interceptor接口提供了三個方法分別是攔截器處理邏輯的主要方法、判斷是否要進行攔截,然后做出決定是否生成一個代理的方法及設置參數的方法。

    package org.apache.ibatis.plugin;
    
    import java.util.Properties;
    
    public interface Interceptor {
    
      Object intercept(Invocation invocation) throws Throwable;
    
      default Object plugin(Object target) {
        return Plugin.wrap(target, this);
      }
    
      default void setProperties(Properties properties) {
        // NOP
      }
    }

    這里說的提升點,就是在實現接口的實現類中,我們可以在plugin方法里加上一個判斷,因為默認情況下,攔截器根據順序攔截后,就可以去處理對應邏輯了,這里加上一個判斷攔截的條件,可以減少代理類的創建。

        @Override
        public Object plugin(Object target) {
            if (target instanceof StatementHandler && checkIfNeeded((StatementHandler) target)) {
                return Plugin.wrap(target, this);
            } else {
                return target;
            }
        }

    以上就是“mybatis攔截器怎么使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    大同县| 曲水县| 嘉兴市| 盐山县| 北安市| 太康县| 广昌县| 莱阳市| 随州市| 孙吴县| 米易县| 武川县| 靖西县| 淳安县| 平果县| 宝坻区| 富源县| 福州市| 上林县| 隆尧县| 徐州市| 商城县| 若尔盖县| 中宁县| 凉城县| 长岛县| 石屏县| 和田市| 游戏| 文昌市| 竹溪县| 上思县| 鹿邑县| 西丰县| 黔西县| 应城市| 甘南县| 澄城县| 辉县市| 凤城市| 水城县|