Struts2攔截器Interceptor原理與配置的示例分析

這篇文章將為大家詳細(xì)講解有關(guān)Struts2攔截器Interceptor原理與配置的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

為余慶等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及余慶網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、余慶網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

一、Struts2攔截器原理:

Struts2攔截器的實(shí)現(xiàn)原理相對(duì)簡(jiǎn)單,當(dāng)請(qǐng)求struts2的action時(shí),Struts 2會(huì)查找配置文件,并根據(jù)其配置實(shí)例化相對(duì)的    攔截器對(duì)象,然后串成一個(gè)列表,最后一個(gè)一個(gè)地調(diào)用列表中的攔截器。

比如:應(yīng)用要求用戶(hù)登陸,且必須為指定用戶(hù)名才可以查看系統(tǒng)中某個(gè)視圖資源;否則,系統(tǒng)直接轉(zhuǎn)入登陸頁(yè)面。對(duì)于上面的需求,可以在每個(gè)Action的執(zhí)行實(shí)際處理邏輯之前,先執(zhí)行權(quán)限檢查邏輯,但這種做法不利于代碼復(fù)用。因?yàn)榇蟛糠諥ction里的權(quán)限檢查代碼都大同小異,故將這些權(quán)限檢查的邏輯放在攔截器中進(jìn)行將會(huì)更加優(yōu)雅。

PS:

1. Struts2攔截器是在訪(fǎng)問(wèn)某個(gè)Action或Action的某個(gè)方法,字段之前或之后實(shí)施攔截,并且Struts2攔截器是可插拔的,攔截器是AOP的一種實(shí)現(xiàn).

2. 攔截器棧(Interceptor Stack)。Struts2攔截器棧就是將攔截器按一定的順序聯(lián)結(jié)成一條鏈。在訪(fǎng)問(wèn)被攔截的方法或字段時(shí),Struts2攔截器鏈中的攔截器就會(huì)按其之前定義的順序被調(diào)用。

二、Struts2 攔截器接口實(shí)現(xiàn):

Struts2規(guī)定用戶(hù)自定義攔截器必須實(shí)現(xiàn)com.opensymphony.xwork2.interceptor.Interceptor接口。該接口聲明了3個(gè)方法,其中,init和destroy方法會(huì)在程序開(kāi)始和結(jié)束時(shí)各執(zhí)行一遍,不管使用了該攔截器與否,只要在struts.xml中聲明了該Struts2攔截器就會(huì)被執(zhí)行。intercept方法就是攔截的主體了,每次攔截器生效時(shí)都會(huì)執(zhí)行其中的邏輯。

void init();
void destroy();
String intercept(ActionInvocation invocation) throws Exception;

1:所有攔截器都使用接口Interceptor ,Action去實(shí)現(xiàn)這個(gè)接口;

  • Init()方法:在服務(wù)器起動(dòng)的時(shí)候加載一次,并且只加載一次;

  • Destroy()方法:當(dāng)攔截器銷(xiāo)毀時(shí)執(zhí)行的方法;

  • Interceptor()方法:其中里邊有一個(gè)參數(shù)invocation;

public String intercept(ActionInvocation invocation) throws xception {
System.out.println("interceptor!!");
String result=invocation.invoke();
return result;
}

其中intercept方法是攔截器的核心方法,所有安裝的攔截器都會(huì)調(diào)用之個(gè)方法。在Struts2中已經(jīng)在struts-default.xml中預(yù)定義了一些自帶的攔截器,如timer、params等。如果在<package>標(biāo)簽中繼承struts-default,則當(dāng)前package就會(huì)自動(dòng)擁有struts-default.xml中的所有配置。

Invocation.invoke()是如果只有一個(gè)攔截器執(zhí)行完這個(gè)方法后,會(huì)返回給視圖,如果有多個(gè)攔截器,它順序的執(zhí)行完所有的攔截器,才返回給視圖,也就是調(diào)用后面的action繼續(xù)執(zhí)行。

二、Struts2 攔截器詳細(xì)配置:

默認(rèn)攔截器是在不設(shè)置任何攔截器的時(shí)候,給予默認(rèn)設(shè)置的,當(dāng)只要設(shè)置任何一個(gè)攔截器就會(huì)覆蓋掉默認(rèn)攔截器, 故此,我們需要手動(dòng)設(shè)置

一旦實(shí)現(xiàn)了檢查攔截器,就可以在所有需要實(shí)現(xiàn)權(quán)限控制的Action中復(fù)用上面的攔截器。

為了使用該攔截器,首先在struts.xml文件中定義攔截器,定義攔截器的配置片段如下:

<!-- 用戶(hù)攔截器定義在該元素下 --> 
<interceptors> 
<!-- 定義了一個(gè)名為authority的攔截器 --> 
<interceptor name="authority" class="lee.AuthorityInterceptor"/> 
</interceptors> 
定義了該攔截器之后,可以在Action中應(yīng)用該攔截器,應(yīng)用該攔截器的配置片段如下: 
<!-- 定義一個(gè)名為viewBook的Action,其實(shí)現(xiàn)類(lèi)為ActionSupport --> 
<action name="viewBook"> 
<!-- 返回success視圖名時(shí),轉(zhuǎn)入/WEB-INF/jsp/viewBook.jsp頁(yè)面 --> 
<result>/WEB-INF/jsp/viewBook.jsp</result> 
<!-- 攔截器一般配置在result元素之后! --> 
<interceptor-ref name="defaultStack"/> 
<!-- 應(yīng)用自定義攔截器 --> 
<interceptor-ref name="authority"/> 
</action>

上面名為viewBook的Action,沒(méi)有指定class屬性,默認(rèn)使用ActionSupport類(lèi),配置該Action時(shí),只是指定了一個(gè)Result,指定返回success字符串時(shí),系統(tǒng)將轉(zhuǎn)入/WEBINF/jsp/viewBook.jsp頁(yè)面。但并為未配置login視圖對(duì)應(yīng)的JSP頁(yè)面。

考慮到這個(gè)攔截器的重復(fù)使用,可能在多個(gè)Action都需要跳轉(zhuǎn)到login邏輯試圖,故將login Result定義成一個(gè)全局Result。

下面是配置login Result的配置片段:

<!-- 定義全局Result -->
<global-results>
<!-- 當(dāng)返回login視圖名時(shí),轉(zhuǎn)入/login.jsp頁(yè)面 -->
<result name="login">/login.jsp</result>
</global-results>

經(jīng)過(guò)上面的配置,如果瀏覽者在瀏覽器中直接發(fā)送viewBook請(qǐng)求,將會(huì)轉(zhuǎn)入如圖所示的頁(yè)面。

這種通過(guò)攔截器進(jìn)行權(quán)限控制的方式,顯然具有更好的代碼復(fù)用。

如果為了簡(jiǎn)化struts.xml文件的配置,避免在每個(gè)Action中重復(fù)配置該攔截器,可以將該攔截器配置成一個(gè)默認(rèn)攔截器棧(這個(gè)默認(rèn)攔截器棧應(yīng)該包括default-stack攔截器棧和權(quán)限檢查攔截器)。

定義自己的默認(rèn)攔截器棧的配置片段如下:

<interceptors>
<!-- 定義權(quán)限檢查攔截器 -->
<interceptor name="authority" class="lee.AuthorityInterceptor"/>
<!-- 定義一個(gè)包含權(quán)限檢查的攔截器棧 -->
<interceptor-stack name="mydefault">
<!-- 定義攔截器棧包含default-stack攔截器棧 -->
<interceptor-ref name="default-stack"/>
<!-- 定義攔截器棧包含authority攔截器 -->
<interceptor-ref name=" authority"/>
</interceptor- stack >
</interceptors>

一旦定義了上面的mydefault攔截器棧,這個(gè)攔截器棧包含了權(quán)限檢查攔截器和系統(tǒng)默認(rèn)的攔截器棧。如果將這個(gè)攔截器棧定義成默認(rèn)攔截器,則可以避免在每個(gè)Action需要重復(fù)定義權(quán)限檢查攔截器。

下面是定義默認(rèn)攔截器的配置片段:

<default-interceptor-ref name="mydefault"/>

一旦在某個(gè)包下定義了上面的默認(rèn)攔截器棧,在該包下的所有Action都會(huì)自動(dòng)增加權(quán)限檢查功能。對(duì)于那些不需要使用權(quán)限控制的Action,將它們定義在另外的包中——這個(gè)包中依然使用系統(tǒng)原來(lái)的默認(rèn)攔截器棧,將不會(huì)有權(quán)限控制功能。

PS:攔截器,攔截器棧和默認(rèn)的攔截器之間的關(guān)系

1:攔截器和攔截器棧是一個(gè)級(jí)別的,也就是說(shuō)一個(gè)攔截器棧中包括許多攔截器, 一個(gè)攔截器棧中還可以包括許多攔截器棧,配置如下方式:

<interceptors>
<!-- 先定義攔截器 -->
<interceptor name="myInterceptor" class="com.struts2.interceptor.MyInterceptor">
<!-- 指定系統(tǒng)初始化給攔截器的參數(shù) -->
<param name="hello">張--</param>
</interceptor>
<!-- 加到自己設(shè)置的攔截器棧里邊去 -->
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor">
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>

攔截器的使用:

1.先定義;

2.在引用使用;

<interceptor name="myInterceptor" class="com.struts2.interceptor.MyInterceptor">
<interceptor-ref name="myInterceptor">
</interceptor-ref>

2:struts2中有一個(gè)系統(tǒng)默認(rèn)的攔截器棧是 defaultStack,如果你手動(dòng)引用自己的攔截器,系統(tǒng)默認(rèn)的攔截器棧將不起作用;這樣必需手動(dòng)引入系統(tǒng)的攔截器棧

<interceptor-ref name="defaultStack">
</interceptor-ref>

如果想改變系統(tǒng)默認(rèn)的攔截器棧,可以這樣配置:

<default-interceptor-ref name="myStack">
</default-interceptor-ref>

其中myStack是自己定義的攔截器棧名字;

如果攔截器棧中有多個(gè)攔截器,在執(zhí)行action之前的順序跟配置攔截器的順序一致,而在action之后執(zhí)行的順序是相反的;
PS:最后還附加一點(diǎn)過(guò)濾器的東西

過(guò)濾器,是在java web中,你傳入的request,response提前過(guò)濾掉一些信息,或者提前設(shè)置一些參數(shù),然后再傳入servlet或者struts的 action進(jìn)行業(yè)務(wù)邏輯,比如過(guò)濾掉非法url(不是login.do的地址請(qǐng)求,如果用戶(hù)沒(méi)有登陸都過(guò)濾掉),或者在傳入servlet或者 struts的action前統(tǒng)一設(shè)置字符集,或者去除掉一些非法字符

攔截器,是在面向切面編程的就是在你的service或者一個(gè)方法,前調(diào)用一個(gè)方法,或者在方法后調(diào)用一個(gè)方法比如動(dòng)態(tài)代理就是攔截器的簡(jiǎn)單實(shí)現(xiàn),在你調(diào)用方法前打印出字符串(或者做其它業(yè)務(wù)邏輯的操作),也可以在你調(diào)用方法后打印出字符串,甚至在你拋出異常的時(shí)候做業(yè)務(wù)邏輯的操作。

攔截器與過(guò)濾器的區(qū)別 :

      1、攔截器是基于java的反射機(jī)制的,而過(guò)濾器是基于函數(shù)回調(diào)。

      2、攔截器不依賴(lài)與servlet容器,過(guò)濾器依賴(lài)與servlet容器。

      3、攔截器只能對(duì)action請(qǐng)求起作用,而過(guò)濾器則可以對(duì)幾乎所有的請(qǐng)求起作用。

      4、攔截器可以訪(fǎng)問(wèn)action上下文、值棧里的對(duì)象,而過(guò)濾器不能訪(fǎng)問(wèn)。

      5、在action的生命周期中,攔截器可以多次被調(diào)用,而過(guò)濾器只能在容器初始化時(shí)被調(diào)用一次

      6、執(zhí)行順序 :過(guò)濾前 - 攔截前 - Action處理 - 攔截后 - 過(guò)濾后。

過(guò)濾是一個(gè)橫向的過(guò)程,首先把客戶(hù)端提交的內(nèi)容進(jìn)行過(guò)濾(例如未登錄用戶(hù)不能訪(fǎng)問(wèn)內(nèi)部頁(yè)面的處理);過(guò)濾通過(guò)后,攔截器將檢查用戶(hù)提交數(shù)據(jù)的驗(yàn)證,做一些前期的數(shù)據(jù)處理,接著把處理后的數(shù)據(jù)發(fā)給對(duì)應(yīng)的Action;Action處理完成返回后,攔截器還可以做其他過(guò)程(還沒(méi)想到要做啥),再向上返回到過(guò)濾器的后續(xù)操作。

一個(gè)Filter 可負(fù)責(zé)攔截多個(gè)請(qǐng)求或響應(yīng):一個(gè)請(qǐng)求或響應(yīng)也可被多個(gè)請(qǐng)求攔截。

創(chuàng)建一個(gè)Filter 只需兩個(gè)步驟:

(1)創(chuàng)建Filter 處理類(lèi):

(2)在web.xml 文件中配置Filter 。

創(chuàng)建Filter 必須實(shí)現(xiàn)javax.servlet.Filter 接口,在該接口中定義了三個(gè)方法。

      ? void init(FilterConfig config) : 用于完成Filter 的初始化。

      ? void destroy() : 用于Filter 銷(xiāo)毀前,完成某些資源的回收。

      ? void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) : 實(shí)現(xiàn)過(guò)濾功能,該方法就是對(duì)每個(gè)請(qǐng)求及響應(yīng)增加的額外處理。

過(guò)濾器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驅(qū)動(dòng)。在servlet2.4中,過(guò)濾器同樣可以用于請(qǐng)求分派器,但須在web.xml中聲明,<dispatcher>INCLUDE或FORWARD或REQUEST或ERROR</dispatcher>該元素位于filter-mapping中。

實(shí)例教程

下面寫(xiě)一個(gè)自定義攔截器的例子,判斷用戶(hù)是否登錄,就是檢查當(dāng)前用戶(hù)的session中的user屬性是否為空,如果為空,就跳到登錄頁(yè)面,否則,繼續(xù)執(zhí)行.

1.編寫(xiě)攔截器,在interceptor包下常見(jiàn)一個(gè)java類(lèi),名為L(zhǎng)oginInterceptor,繼承AbstractInterceptor:

public class LoginInterceptor extends AbstractInterceptor{

 @Override
 public String intercept(ActionInvocation invocation) throws Exception {

  //得到攔截到的action的名稱(chēng),看是否是login,當(dāng)是login的時(shí)候,不用進(jìn)行下面的檢測(cè)了,直接執(zhí)行下一個(gè)攔截器
  String actionName=invocation.getProxy().getActionName();
  if("login".equals(actionName)){
   return invocation.invoke();
     
  }
  //如果不是login.則判斷是否已登錄,及檢測(cè)session中key為user的值是否存在,如果不存在,跳回到登錄頁(yè)面
  String user=(String)invocation.getInvocationContext().getSession().get("user");
  if(user==null){
   System.out.println("未登錄");
   return "login";
  }
  //進(jìn)行到這里.說(shuō)明用戶(hù)已登錄,則跳轉(zhuǎn)到下一個(gè)攔截器
  return invocation.invoke();
 }

}

2,在struts.xml中配置interceptor,主要特別注意的是,當(dāng)使用了自定義的攔截器后,默認(rèn)攔截器將不起作用,默認(rèn)攔截器實(shí)在struts-default.xml中配置的,當(dāng)引用了自定義攔截器,又想使用struts2提供的默認(rèn)攔截器功能,需要手動(dòng)配置:這里我將默認(rèn)攔截器和我寫(xiě)的進(jìn)行登錄權(quán)限驗(yàn)證的攔截器,寫(xiě)到一個(gè)攔截器棧里,然后調(diào)用這個(gè)默認(rèn)攔截器棧:

<package name="default" namespace="/" extends="struts-default">
 
  <interceptors>
    <!-- 配置自定義的攔截器-->
   <interceptor name="checkLogin" class="com.wang.interceptor.LoginInterceptor"/>
    <!--配置一個(gè)攔截器棧,里面包含自己定義的攔截器和defaultStack默認(rèn)攔截器-->   
      <interceptor-stack name="myStack">
    <interceptor-ref name="defaultStack"></interceptor-ref>
    <interceptor-ref name="checkLogin"></interceptor-ref>
   </interceptor-stack>
  </interceptors>
    <!--引用默認(rèn)的攔截器(棧)-->
  <default-interceptor-ref name="myStack"></default-interceptor-ref>
  
    <!--配置一個(gè)全局結(jié)果集-->
     <global-results>
   <result name="login">/login.jsp</result>
  </global-results>
  <action name="login" class="com.wang.action.LoginAction" >
   <result>/succ.jsp</result>
   <result name="error">/login.jsp</result>
  </action>
 </package>

這里我使用了默認(rèn)攔截器標(biāo)簽,即相當(dāng)于在每個(gè)action標(biāo)簽下,使用了 <interceptor-ref name="myStack"></interceptor-ref>.jsp頁(yè)面和LoginAction類(lèi)這里就省略了.

再來(lái)介紹一下方法攔截器,方法攔截器比action攔截器控制的更加精細(xì),大體實(shí)現(xiàn)方式和action攔截器相同,不同的是它繼承的是MethodFilterInterceptor類(lèi),重寫(xiě)的是doInterceptor()方法,在struts.xml的配置上也有些不同,大體是這樣:

<interceptor-ref name="methodInterceptor">
   <!--配置被攔截的方法-->
   <param name="includeMethods">methodA,methodsB</param> 
  <!--配置不被攔截的方法-->
<param name="excludeMethods">methodsC,methodsD</param>
 </interceptor-ref>

關(guān)于“Struts2攔截器Interceptor原理與配置的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

當(dāng)前文章:Struts2攔截器Interceptor原理與配置的示例分析
網(wǎng)頁(yè)地址:http://www.muchs.cn/article36/gdgdpg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、全網(wǎng)營(yíng)銷(xiāo)推廣、關(guān)鍵詞優(yōu)化、網(wǎng)站制作、微信公眾號(hào)、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站