深入解析Struts攔截器的工作原理
Struts2中有三大核心:ognl,攔截器和action;想要學好Struts2,這三個核心是重中之重;這裡就給大家介紹一下Struts2攔截器的工作原理
。
什麼是攔截器
攔截器是在請求到達Action前後進行的一系列操作,Struts2預設自帶了很大攔截器,這些攔截器定義在struts-default.xml中。Struts2中的攔截器是基於AOP動態代理思想的。關於Struts的結構,有一張很經典的圖:
在這張圖上可以清楚的看到請求經過了Action代理,然後通過了一系列Interceptor最終返回,下面我們就來了解一下,圖中的Interceptor1,2,3是如何工作的。
攔截器的工作原理
在搭建Struts2框架時,我們首先需要在web.xml中配置StrutsPrepareAndExecuteFilter過濾器,這是因為請求會首先經過這個過濾器,然後會經過很多層,最後依次經過每一個攔截器(包括自定義的攔截器)。具體經過了哪些層,可以看下面這張圖:
從這張圖可以看到每一層的包含關係,重點看一下最裡面的兩層,紅色箭頭和黃色箭頭的部分,這兩個方法是一個遞迴呼叫的過程,也就是說,當在invoke()方法中呼叫一個攔截器時,攔截器中會有invocation.invoke()這一句,這一句表明會跳出當前攔截器,回到上一級,呼叫下一個攔截器,當所有的攔截器都呼叫了並且action執行完畢後,會遞歸回調攔截器中沒有執行完畢的內容。那麼invoke()方法中是如何呼叫下一個攔截器的呢?看看原始碼就明白了(最核心的程式碼):
if (interceptors.hasNext()) { final InterceptorMapping interceptorMapping = interceptors.next(); String interceptorMsg = "interceptorMapping: " + interceptorMapping.getName(); UtilTimerStack.push(interceptorMsg); try { Interceptor interceptor = interceptorMapping.getInterceptor(); if (interceptor instanceof WithLazyParams) { interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext); } resultCode = interceptor.intercept(DefaultActionInvocation.this); } finally { UtilTimerStack.pop(interceptorMsg); } } else { resultCode = invokeActionOnly(); }
關於遞迴的過程,我自己畫了一個示意圖:
看完上面的解釋,這時候再回去看一開始的struts框架結構圖的interceptor1,2,3,應該可以很容易理解了。
以上就是我對攔截器的執行的理解,希望能夠幫助到大家!