隨筆 - 312, 文章 - 14, 評(píng)論 - 1393, 引用 - 0

          導(dǎo)航

          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          公告

          關(guān)注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團(tuán)隊(duì)

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊(cè)

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務(wù)

          代理網(wǎng)站

          關(guān)注的網(wǎng)站

          協(xié)議

          喜歡的Blog

          國(guó)內(nèi)廣告平臺(tái)

          圖書出版

          在線培訓(xùn)

          開發(fā)工具

          微博客戶端

          手機(jī)鈴聲

          操作系統(tǒng)

          • ReactOS
          • 一個(gè)與windowXP/2003兼容的操作系統(tǒng)

          數(shù)學(xué)

          文件格式

          源碼資源

          移動(dòng)(Mobile)

          編程語言

          英語學(xué)習(xí)

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1972415
          • 排名 - 6

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          Struts2教程9:實(shí)現(xiàn)自已的攔截器

          本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!

          上一篇:Struts2教程8:攔截器概述

              在上一篇中介紹了Struts2攔截器的原理,在這一篇中我們將學(xué)習(xí)一下如何編寫自己的攔截器。

          一、攔截器的實(shí)現(xiàn)

               實(shí)現(xiàn)一個(gè)攔截器非常簡(jiǎn)單。實(shí)際上,一個(gè)攔截器就是一個(gè)普通的類,只是這個(gè)類必須實(shí)現(xiàn)com.opensymphony.xwork2.interceptor.Interceptor接口。Interceptor接口有如下三個(gè)方法:


          public interface Interceptor extends Serializable 
          {
              
          void destroy();
              
          void init();
              String intercept(ActionInvocation invocation) 
          throws Exception;
          }

          其中initdestroy方法只在攔截器加載和釋放(都由Struts2自身處理)時(shí)執(zhí)行一次。而intercept方法在每次訪問動(dòng)作時(shí)都會(huì)被調(diào)用。Struts2在調(diào)用攔截器時(shí),每個(gè)攔截器類只有一個(gè)對(duì)象實(shí)例,而所有引用這個(gè)攔截器的動(dòng)作都共享這一個(gè)攔截器類的對(duì)象實(shí)例,因此,在實(shí)現(xiàn)Interceptor接口的類中如果使用類變量,要注意同步問題。

          下面我們來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的攔截器,這個(gè)攔截器通過請(qǐng)求參數(shù)action指定一個(gè)攔截器類中的方法,并調(diào)用這個(gè)方法(我們可以使用這個(gè)攔截器對(duì)某一特定的動(dòng)作進(jìn)行預(yù)處理)。如果方法不存在,或是action參數(shù)不存在,則繼續(xù)執(zhí)行下面的代碼。如下面的URL

          http://localhost:8080/struts2/test/interceptor.action?action=test

          訪問上面的url后,攔截器會(huì)就會(huì)調(diào)用攔截器中的test方法,如果這個(gè)方法不存在,則調(diào)用invocation.invoke方法,invoke方法和Servlet過濾器中調(diào)用FilterChain.doFilter方法類似,如果在當(dāng)前攔截器后面還有其他的攔截器,則invoke方法就是調(diào)用后面攔截器的intercept方法,否則,invoke會(huì)調(diào)用Action類的execute方法(或其他的執(zhí)行方法)。

          下面我們先來實(shí)現(xiàn)一個(gè)攔截器的父類ActionInterceptor。這個(gè)類主要實(shí)現(xiàn)了根據(jù)action參數(shù)值來調(diào)用方法的功能,代碼如下:


          package interceptor;

          import com.opensymphony.xwork2.ActionInvocation;
          import com.opensymphony.xwork2.interceptor.Interceptor;
          import javax.servlet.http.*;
          import org.apache.struts2.*;

          public class ActionInterceptor implements Interceptor
          {
              
          protected final String INVOKE = "##invoke";
             
              
          public void destroy()
              {
                  System.out.println(
          "destroy");
              }

              
          public void init()
              {
                  System.out.println(
          "init");
              }

              
          public String intercept(ActionInvocation invocation) throws Exception
              {    
                  HttpServletRequest request 
          = ServletActionContext.getRequest();
                  String action 
          = request.getParameter("action");
                  System.out.println(
          this.hashCode());
                  
          if (action != null)
                  {
                      
          try
                      {
                          java.lang.reflect.Method method 
          = this.getClass().getMethod(action);
                          String result 
          = (String)method.invoke(this);
                          
          if(result != null)
                          {
                              
          if(!result.equals(INVOKE))
                                  
          return result;
                          }
                          
          else
                              
          return null;
                      }
                      
          catch (Exception e)
                      {
                      }
                  }
                  
          return invocation.invoke();
              }
          }

          從上面代碼中的intercept方法可以看出,在調(diào)用action所指定的方法后,來判斷返回值。可能發(fā)生的情況有三種:

          1.        返回值為null,執(zhí)行return null。

          2.        返回值為INVOKE,執(zhí)行return invockation.invoke()。

          3.        其他情況,執(zhí)行return result。 result表示指定方法的返回值,如上面代碼所示。

              在實(shí)現(xiàn)完上面的攔截器父類后,任何繼承于ActionInterceptor類的攔截器都可以自動(dòng)根據(jù)action的參數(shù)值調(diào)用自身的相應(yīng)方法。下面我們來實(shí)現(xiàn)一個(gè)擁有兩個(gè)動(dòng)作方法testprint的攔截器類。代碼如下:


          package interceptor;

          import javax.servlet.http.HttpServletResponse;
          import org.apache.struts2.ServletActionContext;

          public class MultiMethodInterceptor extends ActionInterceptor
          {
              
          public String test() throws Exception
              {
                  HttpServletResponse response 
          = ServletActionContext.getResponse();
                  response.getWriter().println(
          "invoke test");
                  
          return this.INVOKE;
              }

              
          public String print() throws Exception
              {
                  HttpServletResponse response 
          = ServletActionContext.getResponse();
                  response.getWriter().println(
          "invoke print");

                  
          return null;
              }
          }

          test方法返回了INVOKE,因此,在執(zhí)行完這個(gè)方法后,Struts2會(huì)接著調(diào)用其他攔截器的intercept方法或Action類的execute方法。而print方法在執(zhí)行完后,只是返回了null,而不再調(diào)用其他的方法了,也就是訪問如下的url時(shí),動(dòng)作的execute方法將不會(huì)執(zhí)行:

              http://localhost:8080/struts2/test/ddd.action?action=print

              下面我們來實(shí)現(xiàn)一個(gè)Action類,代碼如下:

          package action;

          import org.apache.struts2.*;
          import com.opensymphony.xwork2.ActionSupport;

          public class InterceptorAction extends ActionSupport
          {
              
          public String abcd() throws Exception
              {
                  ServletActionContext.getResponse().getWriter()
                          .println(
          "invoke abcd");
                  
          return null;
              }
          }

          在這個(gè)Action類中,只有一個(gè)abcd方法,實(shí)際上,這個(gè)方法相當(dāng)于execute方法,在下面會(huì)設(shè)置動(dòng)作的method屬性為abcd。下面我們來在struts.xml中定義攔截器類和動(dòng)作,代碼如下:


          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE struts PUBLIC
              "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
              "http://struts.apache.org/dtds/struts-2.0.dtd"
          >
          <struts>
              
          <package name="demo" extends="struts-default" namespace="/test">
                  
          <interceptors>
                      
          <interceptor name="method" class="interceptor.MultiMethodInterceptor" />
                          
          <interceptor-stack name="methodStack">
                              
          <interceptor-ref name="method" />
                              
          <interceptor-ref name="defaultStack" />
                          
          </interceptor-stack>
                  
          </interceptors>

                  
          <action name="interceptor" class="action.InterceptorAction" method="abcd">
                      
          <interceptor-ref name="methodStack" />
                  
          </action>
              
          </package>
          </struts>

          在配置上面的methodStack攔截器時(shí)要注意,最好在后面引用defaultStack,否則很多通過攔截器提供的功能將失去。

          OK,現(xiàn)在訪問如下的URL

              http://localhost:8080/struts2/test/ddd.action?action=test

          在瀏覽器中將會(huì)出現(xiàn)如下的字符串:

              invoke test

          invoke abcd

          而如果訪問http://localhost:8080/struts2/test/ddd.action?action=print,將會(huì)只出現(xiàn)如下的字符串:

              invoke print

          大家可以看出,訪問這個(gè)url時(shí)并沒有調(diào)用abcd方法。如果隨便指定的action值的話,則只調(diào)用abcd方法,如訪問http://localhost:8080/struts2/test/ddd.action?action=aaa,就只會(huì)輸出invoke abcd


          二、攔截器的參數(shù)

             
          我們?cè)谑褂煤芏?/span>Struts2內(nèi)置的攔截器時(shí)會(huì)發(fā)現(xiàn)有很多攔截器都帶參數(shù),當(dāng)然。我們自己做的攔截器也可以加上同樣的參數(shù)。有兩個(gè)參數(shù)比較常用,這兩個(gè)參數(shù)是includeMethodsexcludeMethods,其中includeMethods指定了攔截器要調(diào)用的Action類的執(zhí)行方法(默認(rèn)是execute),也就是說,只有在includeMethods中指定的方法才會(huì)被Struts2調(diào)用,而excludeMethods恰恰相反,在這個(gè)參數(shù)中指定的執(zhí)行方法不會(huì)被Struts2調(diào)用。如果有多個(gè)方法,中間用逗號(hào)(,)分隔。在Struts2中提供了一個(gè)抽象類來處理這兩個(gè)參數(shù)。這個(gè)類如下:

          com.opensymphony.xwork2.interceptor.MethodFilterInterceptor

             
          如有繼承于這個(gè)類的攔截器類都會(huì)自動(dòng)處理includeMethodsexcludeMethods參數(shù),如下面的攔截器類所示:

          package interceptor;

          import com.opensymphony.xwork2.ActionInvocation;
          import com.opensymphony.xwork2.interceptor.*;

          public class MyFilterInterceptor extends MethodFilterInterceptor
          {
              
          private String name;
              
          public String getName()
              {
                  
          return name;
              }
              
          public void setName(String name)
              {
                  
          this.name = name;
              }
              @Override
              
          protected String doIntercept(ActionInvocation invocation) throws Exception
              {
                  System.out.println(
          "doIntercept");
                  System.out.println(name);
                  
          return invocation.invoke();
              }
          }

              MethodFilterInterceptor的子類需要實(shí)現(xiàn)doIntercept方法(相當(dāng)于Interceptorintercept方法),如上面代碼所示。在上面的代碼中還有一個(gè)name屬性,是為了讀取攔截器的name屬性而設(shè)置的,如下面的配置代碼所示:


          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE struts PUBLIC
              "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
              "http://struts.apache.org/dtds/struts-2.0.dtd"
          >
          <struts>
              
          <package name="demo" extends="struts-default" namespace="/test">
                  
          <interceptors>
                      
          <interceptor name="method" class="interceptor.MultiMethodInterceptor" />
                          
          <interceptor name="filter"
                              class
          ="interceptor.MyFilterInterceptor">
                              
          <param name="includeMethods">abcd</param>
                              
          <param name="name">中國(guó)</param>
                          
          </interceptor>
                          
          <interceptor-stack name="methodStack">
                              
          <interceptor-ref name="method" />
                              
          <interceptor-ref name="filter" />
                              
          <interceptor-ref name="defaultStack" />
                          
          </interceptor-stack>
                  
          </interceptors>

                  
          <action name="interceptor" class="action.InterceptorAction" method="abcd">
                      
          <interceptor-ref name="methodStack" />
                  
          </action>
              
          </package>
          </struts>

              再次訪問http://localhost:8080/struts2/test/ddd.action?action=test, Struts2就會(huì)調(diào)用MyFilterInterceptordoIntercept方法來輸出name屬性值。如果將上面的includeMethods參數(shù)值中的abcd去掉,則Action類的abcd方法不會(huì)被執(zhí)行。

          下一篇:Struts2教程10:國(guó)際化







          Android開發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺(tái)灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2008-05-09 20:14 銀河使者 閱讀(18664) 評(píng)論(10)  編輯  收藏 所屬分類: Struts2 原創(chuàng)

          評(píng)論

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          博主介紹的很詳細(xì).學(xué)習(xí)了.
          2008-05-16 01:46 | star

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          再次訪問http://localhost:8080/struts2/test/ddd.action?action=test, Struts2就會(huì)調(diào)用MyFilterInterceptor的doIntercept方法來輸出name屬性值。如果將上面的includeMethods參數(shù)值中的abcd去掉,則Action類的abcd方法不會(huì)被執(zhí)行。

          這句話我還是不能理解
          加上includeMethods參數(shù)值abcd是會(huì)被執(zhí)行;可你說去掉abcd就不會(huì)被執(zhí)行我測(cè)試不對(duì)哦,去掉includeMethods參數(shù)值就等于沒有用這個(gè)特性,那樣的話test方法有INVOKE返回值還是會(huì)繼續(xù)執(zhí)行下去。
          2008-05-20 13:34 | 小哥

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          是這樣的,struts2在調(diào)用所定義的攔截器的doIntercept方法后,最后會(huì)調(diào)用相應(yīng)的動(dòng)作類的執(zhí)行方法,默認(rèn)是execute。abcd只是修改了默認(rèn)值,將執(zhí)行方法由execute變成了abcd。如果在includeMethods參數(shù)中包含了abcd,那么Struts2在調(diào)用完所有的doIntercept方法后,就不會(huì)再調(diào)用abcd方法了。
          2008-05-20 15:25 | 銀河使者

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器[未登錄]  回復(fù)  更多評(píng)論   

          @銀河使者

          樓主整理的文章和例子很不錯(cuò),贊一個(gè)。

          不過文章中最后一句話是有些歧義的,如樓上@小哥的問題。文中

          “如果將上面的includeMethods參數(shù)值中的abcd去掉,則Action類的abcd方法不會(huì)被執(zhí)行。 ”

          這句話應(yīng)該理解為這樣:

          “如果將上面的includeMethods參數(shù)值中的abcd去掉,則該過濾器對(duì)方法為‘a(chǎn)bcd’請(qǐng)求將不做限制(也就是不執(zhí)行過濾器MyFilterInterceptor的doIntercept方法),直接執(zhí)行Action類的abcd的方法。 ”
          2009-02-03 17:32 | Sam

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          @Sam
          先謝謝你咯,如果不是看你在下面的解釋,可能我就卡在這里過不去了!
          2009-12-11 13:25 | 請(qǐng)求權(quán)

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          博主,在你的文章里我學(xué)到很多東西,非常感謝,但是對(duì)這點(diǎn)我不是很理解。上面this.getClass().getMethod(action);,好像this.getClass()得到的是ActionInterceptor 的Class對(duì)象,而不是對(duì)應(yīng)action的Class對(duì)象啊,那么也不可能調(diào)用到aciton的方法啊?如果我說錯(cuò)了請(qǐng)博主指點(diǎn)一下。
          2010-07-19 11:22 | liuyake

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          可以,很有收獲
          2012-03-26 09:28 |

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器[未登錄]  回復(fù)  更多評(píng)論   

          11
          2012-03-27 17:59 | 222

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          ssssssssssssssssss
          2014-04-22 15:28 | ddddddddd

          # re: Struts2教程9:實(shí)現(xiàn)自已的攔截器  回復(fù)  更多評(píng)論   

          為什么我直接復(fù)制都跑不出來啊
          2014-07-28 16:18 | 側(cè)田
          主站蜘蛛池模板: 福贡县| 二手房| 临武县| 原平市| 行唐县| 威海市| 修武县| 娄烦县| 蓬莱市| 阿瓦提县| 平遥县| 襄城县| 安庆市| 天津市| 慈利县| 乐山市| 云南省| 清远市| 南宁市| 峡江县| 石台县| 长丰县| 清河县| 定日县| 周口市| 巴彦县| 阜新| 凤阳县| 卓尼县| 若尔盖县| 常德市| 东光县| 永安市| 特克斯县| 建阳市| 浪卡子县| 扎赉特旗| 东阳市| 中山市| 康定县| 温州市|