Struts2 ---攔截器的理解
攔截器(interceptor)是Struts2最強大的特性之一,也可以說是struts2的核心,攔截器可以讓你在Action和result被執行之前或之後進行一些處理。同時,攔截器也可以讓你將通用的程式碼模組化並作為可重用的類。
Struts2中的很多特性都是由攔截器來完成的。攔截是AOP的一種實現策略。攔截器是動態攔截Action呼叫的物件。它提供了一種機制可以使開發者可以定義在一個action執行的前後執行的程式碼,也可以在一個action執行前阻止其執行。同時也是提供了一種可以提取action中可重用的部分的方式。
我個人的理解是在Action和result執行前後新增新的功能.
比如在登入一個頁面時,如果要求使用者密碼、許可權等的驗證,就可以用自定義的攔截器進行密碼驗證和許可權限制。對符合的登入者才跳轉到正確頁面。這樣如果有新增許可權的話,不用在action裡修改任何程式碼,直接在interceptor裡修改就行了。
/////////////////////////////以下為轉載
看了浪曦的STRUTS2的視訊之後,才發現攔截器是多麼滴好用,以下是轉載內容:
攔截器的作用主要就是攔截東西,攔截什麼呢?當然是'action'了,在執行'action'之前 攔截器會起作用,執行一些預先處理的程式碼,
接著區執行action中相關的方法,之後,流程又會回到攔截器裡面,接著去執行後續的一些操作。
先看配置,這些配置都是在struts.xml裡面的。配置相當簡單,不過底層都是很複雜的。在這章之前,我專門看了下動態代理,感覺真的是開發者花了不少的心血,
首先先建一個包,放我們的interceptor。
過濾器和攔截器是非常相似的,public interface Filter類裡面有三個方法:
init(FilterConfig filterConfig),destroy(),doFilter(ServletRequest request,ServletResponse response,FilterChain chain),
這裡面的doFilter()方法是最重要的,在struts2中就相當於攔截的那個方法。
先寫一個攔截器,在struts2中要實現一個介面 這個介面是什麼呢?在哪呢?是webwork是我們以前聽的最多的關於攔截器的框架,
struts2用了其中一個核心的東西,這個東西在是什麼呢?是xwork恩,有了它才可以攔截,好了我們在哪找呢?
在com.opensymphony.xwork2.interceptor中找,裡面有個Interceptor 這是個介面,裡面也有三個方法,
有init,destroy和intercept三個方法,而在struts2裡面的所有的攔截器都繼承這個介面!
就依照這個介面寫一個攔截器類,呵呵!
package com.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor{
private String hello;//一定要寫
get和set方法
public void destroy() {
System.out.println("destory");
}
public void init() {
System.out.println("init");
}
public String intercept(ActionInvocation invoker) throws Exception {
System.out.println("intercept");
String result=invoker.invoke();
// System.out.println("finish1");
return result;
}
}
為了看這些是怎麼實現的,加入了一些列印!
Intercept方法返回一個字串,這個裡面最重要的是ActionInvocation 也是個抽象的介面,裡面有個invoke() 方法
作用:Invokes the next step in processing this ActionInvocation. 即呼叫下一個攔截器,如果有的話!
為了,讓struts2知道我們寫了個攔截器,就在struts。Xml中配置一下。
<package name="struts2" extends="struts-default">
<interceptors>
<interceptor name="myinterceptor" class="com.interceptor.MyInterceptor">
<param name="hello">world</param>
</interceptor>
</interceptors>
註釋:action是寫的一個註冊頁面,也可以隨便用個action 在這個點上是不影響需要檢驗結果的
<action name="register" class="com.test.action.RegisterAction" >
<result name="input">/register.jsp</result>
<result name="success">/success.jsp</result>
</package>
好了到了這裡 攔截器也配置好了,但是攔截器是攔截action的,怎麼才能讓action被攔截呢?
一般的情況下,放在result後面 怎麼寫呢?好了,如下:
<interceptor-ref name="myinterceptor">
</interceptor-ref>
這樣就可以讓aciton被攔截了,到此,好了,可以執行程式了:
輸出結果是:啟動伺服器init被打出
執行後提交action 輸出intercept
這個就是初步的一個攔截器。
=======在此可能出現一個問題,是什麼呢?如果就我們做的登陸而言,當然登陸大家都做的很多了,可以想一下,有資料轉換,有驗證資料是否符合我們的要求====
Ok 如果按照上述執行的話,當資料轉換,驗證出錯的時候,就不會有提示,為什麼呢? 這裡就和struts2的預設攔截器有關係!
這裡可以開啟一個檔案看一下,看了就會明白,是什麼檔案呢?struts-default。Xml
這裡定義的很多的東西,和我們的程式相關的非常緊密
首先這裡有個
<package name="struts-default" abstract="true">和struts.Xml裡面的
<package name="struts2" extends="struts-default">有什麼一樣呢?很明顯可以猜到struts.Xml中繼承的就是default。Xml中的struts-default。
這個裡面還有個<interceptors>和</interceptors>這個是定義攔截器的,仔細看可以發現裡面有個validation 如此可以猜想,
validation 也是定義的一個攔截器,可是最後當登陸出錯後沒有提示資訊呢?肯定是相關的東西沒有執行,以前的執行了,現在沒執行,
在新加了個攔截器後,這樣說明了,是現有的攔截器取代了原有的攔截器,這個是我僅能想到的!結果就是這個樣子的。那麼我們手工吧把原來的預設攔截器加入,這樣可以嗎?
答案是可以的!新增如下!
接著上面result後面新增一個把!
<interceptor-ref name="defaultStack"></interceptor-ref>
這樣還可以說明:如果我們沒有新增攔截器的話,預設的攔截器會自動新增到裡面。
攔截器棧
過濾器可以組成過濾器鏈,就是可以有多個過濾器來去過濾一個元件,攔截器也是,只不過是叫攔截器棧(相當於串攔截器)。
攔截器棧先把攔截器逐個執行,接著執行action方法,之後又按照相反的順序回到最後的一個攔截器,再回到檢視。
攔截器棧是怎麼構成的呢?繼續看struts-default.Xml這個檔案!裡面有這些東西:
<interceptor-stack name="defaultStack">
<interceptor-ref name="static-params"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
這裡面看見了 棧是什麼樣的結構,是由很多個預先定義好的攔截器構成,而且也可以再加上攔截器棧組成,就如此就組成了!
還有這行程式碼:
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
這個是定義預設的攔截器,竟然是預設的當然只可能有一個!是把!
好了,到了這裡,就來有進一步學習struts2的攔截器把!讓我們自己配置自己的攔截器棧!
在開始 的時候我們新增的第一個myinterceptor攔截器的時候我新增了一個引數
<param name="hello">world</param> 這裡我們可以通過配置檔案,給攔截器新增一個引數,那這個在攔截器中怎麼取得的呢?
瞭解過濾器的朋友都知道,裡面有個init(FilterConfig filterConfig)方法這樣可以取值,而在struts2中沒有這麼麻煩,做法嗎,
上面其實已經給出來了!
private String hello;
get和set方法
寫個變數,然後加上get和set方法,當然變數的名字必須和設定的引數是相同的,這個是賦值成功的前提條件
此時,執行,成功輸出:world 這裡的引數使用是在定義攔截器的時候,還有一種是在使用攔截器的時候新增引數。怎麼做呢?
定義攔截器的情況:
<interceptor name="myinterceptor" class="com.interceptor.MyInterceptor">
<param name="hello">world</param>
</interceptor>
使用攔截器的時候的情況:
<interceptor-ref name="myinterceptor">
<param name="hello">zhuxinyu</param>
</interceptor-ref>
這下知道了嗎,還有,當出現如上引用的時候給同樣的引數設定了不同的值,會顯示那一個呢,在執行的時候?
結果是:zhuxinyu 很明顯 覆蓋了第一個 結論是:使用的時候比定義的時候更加厲害,這叫撒,縣官不如現管!
好了,把這些零散的東西搞完了,真的開始解決更多的知識!
攔截器棧,在struts2裡面,其實是把攔截器和攔截器棧一樣的對待。可以把攔截器棧當作一個攔截器看待,同樣的引用。
現在定義一個攔截器棧把!
同樣在<interceptors> </interceptors>裡面定義
<interceptor-stack name="mystack">
<interceptor-ref name="myinterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
看見了沒,一個引用第一次定義的myinterceptor攔截器,一個引用預設的攔截器,怎麼引用呢,和開始的一個樣,呵呵!
<interceptor-ref name=" mystack ">
</interceptor-ref>
呵呵 ,這樣看是不是比剛才簡單呢?把兩次引用換成一次!執行結果呢?和上次一樣,而且都成功!
當然我們也可以自己定義一個預設的攔截器,這樣在程式中怎麼做呢?呵呵,定義如下
<default-interceptor-ref name="mystack"></default-interceptor-ref>
這裡引用的就是上面的mystack攔截器,這樣在程式中如果不在action中加入攔截器,它同樣可以執行相應的工作,
前面已經說過了,如果不加入任何攔截器的引用,它將把預設的攔截器加入。
我們在做攔截器的時候,剛才實現了Interceptor介面,裡面有三個方法,但是一般的情況下init()和destroy()方法我們用不上,
最關心的就是intercept(ActionInvocation invoker){}方法,所以怎麼辦呢?其實,struts2給我們提供了一個簡化的攔截器類,這個是什麼呢?
MethodFilterInterceptor 這是一個抽象的類,裡面實現了init()和destroy()方法,所以只要我們繼承這個類,就不用再多寫這兩個方法!
為了驗證是對的,就寫了個方法,實現如下:
public class MyInterceptor2 extends AbstractInterceptor{
protected String doIntercept(ActionInvocation invocation) throws Exception {
System.out.println("my interceptor2");
String result=invocation.invoke();
return result;
}
}
就是這樣一個簡單的東西,呵呵,把它和其他的攔截器一樣的配置,執行,呵呵就可以出來結果了!
當然在這裡還需要指出一點,你安放的攔截器的順序,其實也就是攔截器執行的順序!但是攔截器,不只是在執行execute()方法之前要執行,
而且在execute()方法之後也要執行。給出如下兩個攔截器說明:
1
public String intercept(ActionInvocation invoker) throws Exception {
System.out.println("intercept1");
String result=invoker.invoke();
System.out.println("finish1");
return result;
}
2
public String intercept(ActionInvocation invoker) throws Exception {
System.out.println("intercept2");
String result=invoker.invoke();
System.out.println("finish2");
return result;
}
在配置順序也是一二,結果會輸出什麼呢?
intercept1 intercept2 finish2 finish1 這裡執行攔截器的過程是正著來的,回來的時候是反著的。就像你要進一個很多門的房間一樣。
進去一個,開一個門,為了讓自己能回來的方便一些,這個開啟的門就不要關著了,當你把所有的門進去了後,然後回來,再逐個關門。
這樣的過程就像是這個攔截器執行的過程。
最後講一個方法過濾攔截器,顧名思義,過濾的是方法。其實在struts2中可以在一個action類中寫很多個與aciton的execute方法類似的方法。
只要在struts。Xml中的action新增一個屬性就可以了這個屬性是method比如:
<action name="register"class="com.test.action.RegisterAction" method="test">當然在action類中也有個test()方法
這個攔截器可以細化到攔截到具體的哪一個方法。如果不是方法過濾攔截器 哪麼它可能將與execute()方法類似的方法都執行。
比如說上面的test()方法。如此這樣照成很多的不必要。於是這種攔截器就顯的格外的重要。
在這個類繼承後實現的不是inteceptor()方法而是doIntercept(),可是做好這個類後如何配置繼承MethodFilterInterceptor這個類呢?
如下(為了實現過濾方法加入了幾個引數,其他的都相同):
<interceptor-ref name="myinterceptor2">
<param name="includeMethods">execute,test</param>
</interceptor-ref>
includeMethods 包含execute,test這兩個方法,結果執行了這個攔截器,如果改成excludeMethods ,就不會執行了,也可以再加下面的一個引數
<param name="excludeMethods">execute,test</param>
不排除execute,test這兩個方法 可是又加入又排除到底執行嗎?答案是執行的,必定結果是最能說明問題的!
------------------------------------------------------馬士兵版對攔截器的理解----------------------------------------------
攔截器能在action被呼叫之前和被呼叫之後執行一些“程式碼”。Struts2框架的大部分核心功能都是通過攔截器來實現的,如防止重複提交、型別轉換、物件封裝、校驗、檔案上傳、頁面預裝載等等,都是在攔截器的幫助下實現的。每一個攔截器都是獨立裝載的(pluggable),我們可以根據實際的需要為每一個action配置它所需要的攔截器。
在myStruts2專案下,重新對配置檔案作如下修改: <package name="myFirst" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="timer"class="com.opensymphony.xwork2.interceptor.TimerInterceptor" />
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor" />
</interceptors>
<action name="login" class="com.asm.LoginAction">
<interceptor-ref name="timer"></interceptor-ref>
<interceptor-ref name="params"></interceptor-ref>
<result name="loginSuccess">/success.jsp</result>
<result name="loginFailure">/failure.jsp</result>
</action>
</package>
首先在package中定義了兩個攔截器,然後在login action中引用了這兩個攔截器,需要說明的是這裡使用的攔截器都是系統自帶的攔截器。其實在extends所繼承的struts-default中就包含了很多攔截器,也包括我們這裡所用的攔截器,但如果在此action中不使用params攔截器,將會報空指標錯,因為params攔截器的作用是傳遞表單引數,如果不使用此攔截器就不能在action中得到表單引數,所以引用時會報空指標錯。雖然extends繼承的strust-default自帶有params攔截器,但是當我們自己引用了攔截器時,繼承struts-default將不會再為我們分配預設的攔截器(有點類似構造器),但是我們仍然可以通過<interceptor-ref name="defaultStack"/>來繼續使用struts-defalut的攔截器。補充:由於上面的package繼承於struts-default,而我們這裡所用到的timer和params都是在struts-defalut中定義過,所以即使我們在<interceptors>中沒有定義過這兩個攔截器,也可以直接在action中引用。
使用</interceptor-stack>組合多個攔截器:比如我們想把上面的params和timer這兩個攔截器組合:
<interceptor-stack name="timer_param">
<interceptor-ref name="timer" />
<interceptor-ref name="params" />
</interceptor-stack>
然後再在action引用<interceptor-ref name="timer_param"/>”,效果和分別引用兩個是一樣的。其實我們使用strtus-default中的<interceptor-ref name="defaultStack"/>也是使用interceptor-stack方式。
相關文章
- Struts2自定義攔截器
- Struts2教程8:攔截器概述
- Struts2攔截器實現原理
- Struts2中攔截器的簡單實現
- 【Struts2】:攔截器實現方法過濾
- 攔截器,攔截器棧總結
- struts2的execAndWait攔截器使用AI
- Struts2 原始碼分析-----攔截器原始碼解析 --- ParametersInterceptor原始碼
- Spring MVC 中的攔截器的使用“攔截器基本配置” 和 “攔截器高階配置”SpringMVC
- SpringMVC攔截器,設定不攔截的URLSpringMVC
- MyBatis攔截器MyBatis
- Mybatis 攔截器MyBatis
- sql攔截器SQL
- Mybatis中的攔截器MyBatis
- axios攔截器iOS
- Mybatis Interceptor 攔截器MyBatis
- axios 攔截器iOS
- spring攔截器Spring
- Java interceptor 攔截器Java
- SpringMVC攔截器SpringMVC
- 11.JDK動態代理理解與攔截器JDK
- webwork的攔截器真是好用Web
- Java實現的攔截器Java
- grpc中的攔截器RPC
- SpringMVC中的攔截器SpringMVC
- vue中用axios攔截器攔截請求和響應VueiOS
- Flume內建攔截器與自定義攔截器(程式碼實戰)
- SpringMVC-攔截器SpringMVC
- 攔截過濾器模式過濾器模式
- gRPC(3):攔截器RPC
- 【SpringMVC】 4.3 攔截器SpringMVC
- web api新增攔截器WebAPI
- spring boot 攔截器Spring Boot
- SpringMVC配置攔截器SpringMVC
- mybatis註冊攔截器MyBatis
- HandlerInterceptor - 自定義攔截器
- spring mvc 攔截器的使用SpringMVC
- SpringBoot攔截器中獲取註解、攔截器中注入ServiceSpring Boot