鍍金池/ 教程/ Java/ 攔截器
注釋
主題/模板
驗(yàn)證
有用的資源
Struts 2 注解類型
實(shí)例
攔截器
異常處理
表單標(biāo)簽
結(jié)果類型
值棧/OGNL
Spring 集成
數(shù)據(jù)標(biāo)簽
環(huán)境配置
配置
類型轉(zhuǎn)換
動(dòng)作
Hibernate 集成
本地化
發(fā)送郵件
Ajax 標(biāo)簽
數(shù)據(jù)庫訪問
體系結(jié)構(gòu)
文件上傳
Tiles 集成
概述
基本的 MVC 架構(gòu)
控制標(biāo)簽

攔截器

攔截器在概念上和servlet過濾器或JDKs代理類一樣。攔截器允許橫切功能在動(dòng)作和框架中單獨(dú)實(shí)現(xiàn)。你可以使用攔截器實(shí)現(xiàn)下面的內(nèi)容:

  • 在動(dòng)作被調(diào)用之前提供預(yù)處理邏輯。

  • 在動(dòng)作被調(diào)用之后提供預(yù)處理邏輯。

  • 捕獲異常,以便可以執(zhí)行交替處理。

Struts 2 框架提供的許多功能都是使用攔截實(shí)現(xiàn)的;例如包括異常處理,文件上傳,生命周期回調(diào)和驗(yàn)證等。事實(shí)上,由于 Struts 2 是許多攔截器功能的基礎(chǔ),所以每次動(dòng)作不是不可能有 7 個(gè)或 8 個(gè)攔截器被分配。

Struts 2 框架的攔截器

Struts 2 框架提供了一列開箱即用的攔截器來預(yù)先設(shè)定和準(zhǔn)備使用。下面列出了幾個(gè)重要的攔截器:

序號(hào) 攔截器及描述
1 alias

允許參數(shù)有不同的跨請(qǐng)求的別名。

2 checkbox

通過為沒有被檢查的復(fù)選框添加一個(gè)參數(shù)值 false 來協(xié)助管理復(fù)選框。

3 conversionError

把從字符串轉(zhuǎn)化為參數(shù)類型的錯(cuò)誤信息放置到動(dòng)作的字段錯(cuò)誤中。

4 createSession

如果不存在 HTTP 會(huì)話,則自動(dòng)創(chuàng)建一個(gè) HTTP 會(huì)話。

5 debugging

為開發(fā)人員提供幾種不同的調(diào)試屏幕。

6 execAndWait

當(dāng)動(dòng)作在后臺(tái)執(zhí)行的時(shí)侯,把用戶定向到一個(gè)中間的等待頁面。

7 exception

映射動(dòng)作拋出的異常到一個(gè)結(jié)果中,通過重定向允許自動(dòng)異常處理。

8 fileUpload

有利于簡(jiǎn)單的文件上傳。

9 i18n

在用戶的會(huì)話期間,跟蹤選定的語言環(huán)境。

10 logger

通過輸出被執(zhí)行的動(dòng)作的名稱提供簡(jiǎn)單的日志。

11 params

設(shè)置動(dòng)作的請(qǐng)求參數(shù)。

12 prepare

它通常是用來做預(yù)處理工作,如設(shè)置數(shù)據(jù)庫連接。

13 profile

14 scope

在會(huì)話或應(yīng)用程序的范圍中存儲(chǔ)和檢索動(dòng)作的狀態(tài)。

15 ServletConfig

為行動(dòng)提供了各種基于 servlet 信息的訪問。

16 timer

以動(dòng)作需要多長(zhǎng)時(shí)間執(zhí)行的形式提供了簡(jiǎn)單的配置信息。

17 token

為有效的標(biāo)記檢查動(dòng)作用來防止重復(fù)地表單提交。

18 validation

為動(dòng)作提供了驗(yàn)證支持。

關(guān)于上面提到的攔截器的完整信息,請(qǐng)查看 Struts 2 的文檔。但是我會(huì)告訴你通常如何在你的 Struts 應(yīng)用程序中使用一個(gè)攔截器。

如何使用攔截器?

讓我們來看看如何在我們的 “Hello World” 程序中使用已存在的攔截器。我們將使用 timer 攔截器,它的目的是測(cè)量它多長(zhǎng)時(shí)間執(zhí)行一個(gè)動(dòng)作的方法。同時(shí)我使用 params 攔截器,它的目的是給動(dòng)作發(fā)送請(qǐng)求參數(shù)。你可以嘗試在你的例子中不使用這個(gè)攔截器,你將會(huì)發(fā)現(xiàn) name 屬性沒有被設(shè)置,因?yàn)閰?shù)是無法達(dá)到動(dòng)作中的。

我們將保留 HelloWorldAction.java,web.xml,HelloWorld.jsp 和index.jsp 文件,因?yàn)樗麄円呀?jīng)在 Examples 章節(jié)被創(chuàng)建了,但是讓我們修改 struts.xml 文件,添加一個(gè)攔截器,如下所示:

 
<?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>
   <constant name="struts.devMode" value="true" />
   <package name="helloworld" extends="struts-default">
      <action name="hello" 
         class="com.tutorialspoint.Struts 2.HelloWorldAction"
         method="execute">
         <interceptor-ref name="params"/>
         <interceptor-ref name="timer" />
         <result name="success">/HelloWorld.jsp</result>
      </action>
   </package>
</struts>

右鍵單擊項(xiàng)目名稱,并且單擊 Export > WAR File 來創(chuàng)建一個(gè) War 文件。然后在 Tomcat 的 webapps 目錄下部署這個(gè) WAR。最后,啟動(dòng) Tomcat 服務(wù)器和嘗試訪問 URL http://localhost:8080/HelloWorldStruts 2/index.jsp. 將會(huì)給出下面的畫面:

http://wiki.jikexueyuan.com/project/struts-2/images/helloworldstruts4.jpg" alt="" />

現(xiàn)在,在給定的文本框中輸入任何單詞,并且單擊 Say Hello 按鈕執(zhí)行已定義的動(dòng)作?,F(xiàn)在,如果你查看生成的日志,就會(huì)發(fā)現(xiàn)下面的文字:

INFO: Server startup in 3539 ms
27/08/2011 8:40:53 PM 
com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
INFO: Executed action [//hello!execute] took 109 ms.

在這里最后一行是因?yàn)?timer 攔截器生成長(zhǎng)的,它告訴動(dòng)作被執(zhí)行的時(shí)間的 109ms。

創(chuàng)建自定義的攔截器

在你的應(yīng)用程序中使用自定義的攔截器是一種提供橫切的應(yīng)用功能的簡(jiǎn)潔的方式。創(chuàng)建一個(gè)自定義的攔截器是很容易的,需要擴(kuò)展的接口是下面的 Interceptor 接口:

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

正如名稱所顯示的,init() 方法提供了一種初始化攔截器的方法,而destroy() 方法提供了一種清理攔截器的工具。與動(dòng)作不同的是,攔截器在請(qǐng)求之間被重用,而且需要是線程安全的,尤其是 intercept() 方法。

ActionInvocation 對(duì)象提供運(yùn)行時(shí)環(huán)境的訪問。它允許訪問動(dòng)作本身和方法來調(diào)用該動(dòng)作,并判定動(dòng)作是否已經(jīng)被調(diào)用。

如果你不需要初始化或清理代碼,可以擴(kuò)展 AbstractInterceptor 類。它提供了一個(gè)對(duì) init() 和 destroy() 方法的默認(rèn)的無操作實(shí)現(xiàn)。

創(chuàng)建攔截器類

讓我們?cè)?Java Resources > src 文件夾中創(chuàng)建下面的MyInterceptor.java

package com.tutorialspoint.Struts 2;
import java.util.*;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor {
   public String intercept(ActionInvocation invocation)throws Exception{
      /* let us do some pre-processing */
      String output = "Pre-Processing"; 
      System.out.println(output);
      /* let us call action or next interceptor */
      String result = invocation.invoke();
      /* let us do some post-processing */
      output = "Post-Processing"; 
      System.out.println(output);
      return result;
   }
}

如你注意到的,實(shí)際的動(dòng)作將通過使用攔截器調(diào)用 invocation.invoke() 來執(zhí)行。所以,你可以根據(jù)你的需求做一些預(yù)處理和一些后處理。

這個(gè)框架本身通過第一次調(diào)用 ActionInvocation 對(duì)象的 invoke() 來啟動(dòng)過程。每次 invoke() 被調(diào)用,ActionInvocation 查詢它的狀態(tài),并且執(zhí)行接下來的攔截器。當(dāng)所有已配置的攔截器已經(jīng)被配置時(shí),invoke() 方法將引發(fā)這個(gè)動(dòng)作本身被執(zhí)行。下面的圖通過請(qǐng)求流顯示了相同的概念:

http://wiki.jikexueyuan.com/project/struts-2/images/actioninvocation.jpg" alt="" />

創(chuàng)建動(dòng)作類

讓我們?cè)?Java Resources > src 中名為 com.tutorialspoint.Struts 2 的包下創(chuàng)建一個(gè) java 文件HelloWorldAction.java,它的內(nèi)容在下面給出。

package com.tutorialspoint.Struts 2;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorldAction extends ActionSupport{
   private String name;
   public String execute() throws Exception {
      System.out.println("Inside action....");
      return "success";
   }  
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

我們已經(jīng)在前面的例子中看到這個(gè)相同的類。我們對(duì)于 “name” 屬性有標(biāo)準(zhǔn)的 getters 和 setters 方法,還有返回字符串 “success” 的 execute 方法。

創(chuàng)建視圖

讓我們?cè)?eclipse 項(xiàng)目的 WebContent 文件夾中創(chuàng)建下面的 jsp 文件 helloWorld.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
   Hello World, <s:property value="name"/>
</body>
</html>

創(chuàng)建主頁面

我們還需要在 WebContent 文件夾中創(chuàng)建 index.jsp。這個(gè)文件將作為初始動(dòng)作 URL,用戶可以點(diǎn)擊它告訴 Struts 2 框架調(diào)用HelloWorldAction 類定義的方法,并且呈現(xiàn) HelloWorld.jsp 視圖。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello World</title>
</head>
<body>
   <h1>Hello World From Struts 2</h1>
   <form action="hello">
      <label for="name">Please enter your name</label><br/>
      <input type="text" name="name"/>
      <input type="submit" value="Say Hello"/>
   </form>
</body>
</html>

上面的視圖文件中定義的 hello 動(dòng)作將使用 struts.xml 文件映射到 HelloWorldAction 類和它的 execute 方法中。

配置文件

現(xiàn)在,我們需要注冊(cè)我們的攔截器,然后調(diào)用它,就如我們已經(jīng)在前面的例子中調(diào)用了默認(rèn)的攔截器一樣。為了注冊(cè)一個(gè)新定義的攔截器,可以把 ... 標(biāo)簽直接放置在 struts.xml 文件 標(biāo)簽內(nèi)。對(duì)于默認(rèn)的攔截器,你可以跳過這一步,就像我們?cè)谇懊娴睦又幸粯?。但在這里讓我們注冊(cè)和使用它,如下所示:

 
<?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>
   <constant name="struts.devMode" value="true" />
   <package name="helloworld" extends="struts-default">

      <interceptors>
         <interceptor name="myinterceptor"
            class="com.tutorialspoint.Struts 2.MyInterceptor" />
      </interceptors>

      <action name="hello" 
         class="com.tutorialspoint.Struts 2.HelloWorldAction" 
         method="execute">
         <interceptor-ref name="params"/>
         <interceptor-ref name="myinterceptor" />
         <result name="success">/HelloWorld.jsp</result>
      </action>

   </package>
</struts>

應(yīng)該注意的是,你可以在 標(biāo)簽內(nèi)注冊(cè)多個(gè)攔截器,并且同時(shí)你可以在 標(biāo)簽內(nèi)調(diào)用多個(gè)攔截器。你可以用不同的動(dòng)作調(diào)用相同的攔截器。

web.xml 文件需要在 WebContent 的 WEB-INF 文件夾下創(chuàng)建,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">   
   <display-name>Struts 2</display-name>
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   <filter>
      <filter-name>Struts 2</filter-name>
      <filter-class>
         org.apache.Struts 2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>
   <filter-mapping>
      <filter-name>Struts 2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

右鍵單擊項(xiàng)目名稱,并且單擊 Export > WAR File 來創(chuàng)建一個(gè) War文件。然后在 Tomcat 的 webapps 目錄下部署這個(gè) WAR。最后,啟動(dòng)Tomcat 服務(wù)器和嘗試訪問 URL http://localhost:8080/HelloWorldStruts 2/index.jsp/ 將會(huì)給出下面的畫面:

http://wiki.jikexueyuan.com/project/struts-2/images/helloworldstruts4.jpg" alt="" />

現(xiàn)在,在給定的文本框中輸入任何單詞,并且單擊 Say Hello 按鈕執(zhí)行已經(jīng)定義的動(dòng)作?,F(xiàn)在,如果你查看生成的日志,就會(huì)在底部發(fā)現(xiàn)下面的文字:

Pre-Processing
Inside action....
Post-Processing

堆疊多個(gè)攔截器

可想而知,為每個(gè)動(dòng)作配置多個(gè)攔截器很快就會(huì)變得非常難以管理。為此,攔截器用攔截器棧進(jìn)行管理。這兒有一個(gè)例子,直接來自 struts-default.xml 文件:

<interceptor-stack name="basicStack">
   <interceptor-ref name="exception"/>
   <interceptor-ref name="servlet-config"/>
   <interceptor-ref name="prepare"/>
   <interceptor-ref name="checkbox"/>
   <interceptor-ref name="params"/>
   <interceptor-ref name="conversionError"/>
</interceptor-stack>

上面的棧被稱為 basicStack,它可以用在你的配置中,如下所示。這個(gè)配置節(jié)點(diǎn)被放置在 節(jié)點(diǎn)下。每個(gè) 標(biāo)簽引用一個(gè)攔截器或在當(dāng)前的攔截器棧之前已配置的攔截器棧。因此,當(dāng)配置初始的攔截器和攔截器棧時(shí),確保在所有攔截器和攔截器棧配置中這個(gè)名稱是唯一的,這是非常重要的。

我們已經(jīng)看到了如何應(yīng)用攔截器到動(dòng)作中,應(yīng)用攔截器棧是沒有什么不同的。實(shí)際上,我們完全使用相同的標(biāo)簽:

<action name="hello" class="com.tutorialspoint.Struts 2.MyAction">
   <interceptor-ref name="basicStack"/>
   <result>view.jsp</result>
</action

上述注冊(cè)的 “basicStack” 將完整地注冊(cè)所有帶有 hello 動(dòng)作的 6 個(gè)攔截器。應(yīng)該指出的是,攔截器按照已配置的順序執(zhí)行。例如,在上述情況下,將首先執(zhí)行異常,第二個(gè)執(zhí)行的是 servlet 配置等等。

上一篇:概述下一篇:結(jié)果類型