攔截器的概念是Servlet過濾器或JDK代理類一樣的。攔截器允許橫切功能分開實現的動作,以及框架。使用攔截器,可以實現如下:
提供預處理行動之前被稱為邏輯。
提供後處理邏輯動作後被呼叫
捕獲異常,這樣可以進行替代處理。
Struts2框架提供的許多功能都使用攔截實現的例子包括例外處理,檔案上傳,生命週期回撥和驗證等事實上作為Struts2的基礎,其功能攔截,這可能有7或8攔截器分配給每個動作。
Struts 2框架提供了良好的箱攔截列表來預先設定的,並準備使用。下面列出了幾個重要的攔截:
SN | 攔截器 & 描述 |
---|---|
1 |
alias Allows parameters to have different name aliases across requests. |
2 |
checkbox Assists in managing check boxes by adding a parameter value of false for check boxes that are not checked. |
3 |
conversionError Places error information from converting strings to parameter types into the action's field errors. |
4 |
createSession Automatically creates an HTTP session if one does not already exist. |
5 |
debugging Provides several different debugging screens to the developer. |
6 |
execAndWait Sends the user to an intermediary waiting page while the action executes in the background. |
7 |
exception Maps exceptions that are thrown from an action to a result, allowing automatic exception handling via redirection. |
8 |
fileUpload Facilitates easy file uploading. |
9 |
i18n Keeps track of the selected locale during a user's session. |
10 |
logger Provides simple logging by outputting the name of the action being executed. |
11 |
params Sets the request parameters on the action. |
12 |
prepare This is typically used to do pre-processing work, such as setup database connections. |
13 |
profile Allows simple profiling information to be logged for actions. |
14 |
scope Stores and retrieves the action's state in the session or application scope. |
15 |
ServletConfig Provides the action with access to various servlet-based information. |
16 |
timer Provides simple profiling information in the form of how long the action takes to execute. |
17 |
token Checks the action for a valid token to prevent duplicate formsubmission. |
18 |
validation Provides validation support for actions |
請看Struts 2文件的完整細節上面提到的攔截。會告訴如何使用Struts應用程式在一個攔截器。
讓我們來看看如何使用已有的攔截,我們的“Hello World”程式。我們將使用計時器來測量過了多長時間執行操作方法,其目的是攔截。同時使用params攔截器,其目的是傳送請求引數的動作。您可以嘗試不使用這個攔截您的範例中會發現,沒有被設定name屬性,因為引數是無法達到動作。
我們將繼續HelloWorldAction.java,web.xml 的helloWorld.jsp 和 index.jsp 檔案,因為他們已經建立了範例章節,但讓我們如下修改struts.xml檔案,新增一個攔截器
<?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.yiibai.struts2.HelloWorldAction" method="execute"> <interceptor-ref name="params"/> <interceptor-ref name="timer" /> <result name="success">/HelloWorld.jsp</result> </action> </package> </struts>
右鍵點選專案名稱,並單擊 Export > WAR File 建立一個WAR檔案。然後部署在Tomcat 的webapps目錄下這個WAR。最後,啟動Tomcat伺服器和嘗試存取URL http://localhost:8080/HelloWorldStruts2/index.jsp。這會給你以下畫面:
現在,在給定的文字框中輸入單詞,並單擊“Say Hello按鈕執行已定義的動作。現在,如果將檢查生成的紀錄檔,會發現下面的文字:
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.
這裡底行,正在生成因為這告訴動作發生要執行的總共為 109ms定時器的攔截器。
在應用程式中使用自定義的攔截器是一種優雅的方式提供橫切的應用功能。建立一個自定義攔截器是很容易的,需要擴充套件的介面,下面的Interceptor介面:
public interface Interceptor extends Serializable{ void destroy(); void init(); String intercept(ActionInvocation invocation) throws Exception; }
正如其名稱所表明的,init()方法提供了一種方法來初始化攔截器,並destroy() 方法提供了一種工具攔截清理。不同的行動,攔截被重用跨請求和需要是執行緒安全的,尤其是intercept() 方法。
ActionInvocation物件可以存取執行時環境。它允許存取的動作本身和方法呼叫的動作,並確定動作是否已被呼叫。
如果不需要初始化或清除程式碼,可以擴充套件AbstractInterceptor類。這提供了一個預設的無操作實現的init()和 destroy()方法。
讓我們建立Java資源 MyInterceptor.java> src 檔案夾:
package com.yiibai.struts2; 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; } }
就像看到的,實際行動將使用攔截器執行invocation.invoke()呼叫。所以,可以做一些前處理和一些處理後,根據需要。
該框架本身啟動的過程中,在第一次呼叫ActionInvocation物件的invoke()。每次 invoke()被呼叫,ActionInvocation的咨詢的狀態和執行為準攔截接下來。通過請求流以下資料圖顯示了相同的概念:
讓我們建立一個Java檔案HelloWorldAction.java的Java下Java Resources > src下面給出的內容包名為 com.yiibai.struts2。
package com.yiibai.struts2; 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; } }
在前面的例子中,我們已經看到,這是一個相同的類。我們有標準的“名稱”屬性的getter和setter方法??,並返回字串“success”的執行方法。
讓我們建立以下JSP檔案helloWorld.jsp,在eclipse專案在WebContent檔案夾。
<%@ 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>
我們還需要在WebContent檔案夾中建立 index.jsp。該檔案將作為初始動作URL,使用者可以在其中點選告訴Struts 2框架呼叫 HelloWorldAction類定義的方法呈現 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 Struts2</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 動作定義在上面的檢視檔案將被對映到HelloWorldAction類和其執行方法使用struts.xml檔案。
現在,我們需要註冊我們的攔截器,然後呼叫它預設的攔截器在前面的例子中呼叫。要註冊一個新定義的攔截,直接放在的<interceptors>...</interceptors>標籤下<package>的標籤外掛struts.xml檔案。您可以跳過這一步為預設的攔截器,就像我們在我們前面的例子。但在這裡,讓我們註冊和使用它,如下所示:
<?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.yiibai.struts2.MyInterceptor" /> </interceptors> <action name="hello" class="com.yiibai.struts2.HelloWorldAction" method="execute"> <interceptor-ref name="params"/> <interceptor-ref name="myinterceptor" /> <result name="success">/HelloWorld.jsp</result> </action> </package> </struts>
應該指出的是,可以註冊多個攔截器<package>標籤內,同一時間,可以呼叫多個攔截裡面的<action>標籤。可以呼叫相同的攔截器與不同的動作。
web.xml檔案需要在 WEB-INF檔案夾下建立 WebContent 如下:
<?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>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
右鍵點選專案名稱,並單擊 Export > WAR File 檔案建立一個WAR檔案。然後部署在Tomcat 的webapps目錄下這個WAR。最後,啟動Tomcat 伺服器和嘗試存取URL http://localhost:8080/HelloWorldStruts2/index.jsp。這會給你以下畫面:
現在,在給定的文字框中輸入任何單詞,並單擊“Say Hello“ 按鈕執行已定義的動作。現在,如果檢查生成的紀錄檔,會發現下面的文字下方:
Pre-Processing Inside action.... Post-Processing
可以想像,組態多個攔截器每個動作很快就會變得非常難以控制。出於這個原因,攔截器與攔截器棧管理。下面是一個例子,直接從在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,可用於在組態中,如下所示。此組態節點放置在<package.../>節點下。每個<interceptor-ref.../>標記參照一個攔截器或攔截器棧已組態在當前的攔截器棧。因此,這是非常重要的,以確保該名稱是唯一的所有攔截器和攔截器棧組態組態初始的攔截器和攔截器棧時。
我們已經看到了如何應用攔截的動作,將攔截器棧是沒有什麼不同。事實上,我們完全使用相同的標籤:
<action name="hello" class="com.yiibai.struts2.MyAction"> <interceptor-ref name="basicStack"/> <result>view.jsp</result> </action
上述註冊的“basicStack”所有6個攔截器完成註冊的棧 Hello 動作。應該指出的是,攔截器執行的順序在組態中。例如,在上述情況下,異常將被執行,servlet 組態等。