一、前言 之前便瞭解過,Struts 2的核心控制器是一個Filter過濾器,負責攔截所有的用戶請求,當用戶請求發送過來時,會去檢測struts.xml是否存在這個action,如果存在,伺服器便會自動幫我們跳轉到指定的處理類中去處理用戶的請求,基本流程如下: 該流程筆者理解是基本流程,。如果有不對 ...
一、前言
之前便瞭解過,Struts 2的核心控制器是一個Filter過濾器,負責攔截所有的用戶請求,當用戶請求發送過來時,會去檢測struts.xml是否存在這個action,如果存在,伺服器便會自動幫我們跳轉到指定的處理類中去處理用戶的請求,基本流程如下:
該流程筆者理解是基本流程,。如果有不對的地方,請下方留言。我會改正。謝謝;
好,接著往下講:
註意:在struts.xml中,配置文件必須有該請求的處理類才能正常跳轉,同時,返回SUCCESS字元串的類,必須繼承ActionSupport,如果你沒有繼承,那麼就返回"success",同樣能夠跳轉到jsp邏輯視圖,但是必須確保你struts.xml有<result name="success">xx.jsp</result>,該標簽,具體操作在上一篇文章有介紹過簡單例子。
1.1、瞭解攔截器
什麼是攔截器,它的作用是什麼?
攔截器,實際上就是對調用方法的改進。
作用:動態攔截對Action對象的調用,它提供了一種機制可以使開發者可以定義在一個action執行的前後執行的代碼,也可以在一個action執行前阻止其執行。同時也是提供了一種可以提取action中可重用的部分的方式。
攔截器的執行順序:
在執行Action的execute方法之前,Struts2會首先執行在struts.xml中引用的攔截器,在執行完所有引用的攔截器的intercept方法後,會執行Action的execute方法。
二、實際操作
2.1、自定義攔截器
新建一個類繼承AbstractInterceptor。
package com.Interceptor; import java.util.Date; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class MyInterceptor extends AbstractInterceptor { private String name;//該屬性與struts.xml中的<param name="name">簡單攔截器</param>一致,也就是說該name的值是簡單攔截器 public void setName(String name) { this.name = name; } //攔截action請求 @Override public String intercept(ActionInvocation arg0) throws Exception { //取得被攔截的action LoginAction action = (LoginAction)arg0.getAction(); System.out.println(name+":攔截器的動作------"+"開始執行登錄action的時間為:"+new Date()); long start = System.currentTimeMillis(); /* * ActionInvocation.invoke()就是通知struts2接著乾下麵的事情 * 比如 調用下一個攔截器 或 執行下一個Action * 就等於退出了你自己編寫的這個interceptor了 * 在這裡是去調用action的execute方法,也就是繼續執行Struts2 接下來的方法*/ String result = arg0.invoke(); System.out.println(name+":攔截器的動作------"+"執行完登錄action的時間為:"+new Date()); long end = System.currentTimeMillis(); System.out.println(name+":攔截器的動作------"+"執行完該action的時間為:"+(end-start)+"毫秒"); System.out.println(result); //輸出的值是:success return result; } } /** * 該頁面的效果如下: * 簡單攔截器:攔截器的動作------開始執行登錄action的時間為:Mon Oct 24 19:06:17 CST 2016 用戶名:admin,密碼:123 簡單攔截器:攔截器的動作------執行完登錄action的時間為:Mon Oct 24 19:06:18 CST 2016 簡單攔截器:攔截器的動作------執行完該action的時間為:1130毫秒 success * */
在struts.xml中配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!--簡單的攔截器 --> <package name="Interceptor" extends="struts-default" namespace="/ac"> <!-- 跳轉前攔截 --> <interceptors> <!-- 聲明簡單的過濾器 --> <interceptor name="Inter" class="com.Interceptor.MyInterceptor"> <!--傳遞name的參數 --> <param name="name">簡單攔截器</param> </interceptor> </interceptors> <action name="loginaction" class="com.Interceptor.LoginAction"> <result name="success">/Interceptor/welcome.jsp</result> <result name="input">/Interceptor/error.jsp</result> <!--註意:如果不加預設的攔截器的話,那麼類型轉換不會執行,也就是說不會把文本上的值賦值給實體類 --> <interceptor-ref name="defaultStack"/> <!-- 簡單的過濾器,定義在這裡告訴攔截器在此處action執行 --> <interceptor-ref name="Inter"> </interceptor-ref> </action> </package> </struts>
struts.xml解析:
<interceptors>:表示聲明攔截器
<interceptor>: 表示定義一個攔截器
<param>:給該攔截器一個參數,屬性為name
<interceptor-ref name="">:表示該攔截器在這個action中使用。
新建LoginAction類,繼承ActionSupport
package com.Interceptor; import com.opensymphony.xwork2.ActionSupport; //action類處理 public class LoginAction extends ActionSupport { private String username; private String pwd; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } //預設執行execute方法 public String execute(){ System.out.println("用戶名:"+username+",密碼:"+pwd); return SUCCESS; }
新建jsp視圖界面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>簡單的登錄攔截</title> </head> <body> <!--如果在struts.xml中,package包中有配置namespace的話,那麼在此處就應該配置。不然會報404錯誤 --> <s:form action="loginaction" namespace="/ac"> <s:textfield label="User Name" name="username"/> <s:password label="Password" name="pwd" /> <s:submit/> </s:form> </body> </html>
(代碼筆者測試沒問題)
2.2、過濾方法:
攔截器不僅可以定義多個攔截,還可以指定攔截特定的方法。
struts.xml的配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!--簡單的攔截器 --> <package name="Interceptor" extends="struts-default" namespace="/ac"> <!-- 跳轉前攔截 --> <interceptors> <!-- 聲明方法過濾器 --> <interceptor name="myMethod" class="com.Interceptor.MyMethodInterceptor"> <param name="name">方法過濾攔截器</param> </interceptor> </interceptors> <action name="loginaction" class="com.Interceptor.LoginAction" method="method1"> <!-- 如果是攔截方法的話,改為method="method2" --> <result name="success">/Interceptor/welcome.jsp</result> <!-- /Interceptor是筆者文件夾。別弄錯了--> <result name="input">/Interceptor/error.jsp</result> <!--註意:如果不加預設的攔截器的話,那麼類型轉換不會執行,也就是說不會把文本上的值賦值給實體類 --> <interceptor-ref name="defaultStack"/> <!-- 方法過濾器 --> <interceptor-ref name="myMethod"> <param name="name">改名後的方法過濾器</param> <param name="includeMethods">method1,method3</param> <!--表示該方法不被攔截--> <param name="excludeMethods">method2</param> <!--表示該方法被攔截 --> </interceptor-ref> </action> </package> </struts>
修改LoginAction類
package com.Interceptor; import com.opensymphony.xwork2.ActionSupport; //action類處理 public class LoginAction extends ActionSupport { private String username; private String pwd; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } // 過濾的方法 public String method1() throws Exception { System.out.println("Action執行方法:method1()"); return SUCCESS; } public String method2() throws Exception { System.out.println("Action執行方法:method2()"); return SUCCESS; } public String method3() throws Exception { System.out.println("Action執行方法:method3()"); return SUCCESS; } }
新建MyMethodInterceptor類繼承MethodFilterInterceptor
MethodFilterInterceptor類表示你定義的攔截器支持方法過濾。
package com.Interceptor; import java.util.Date; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; //過濾方法 public class MyMethodInterceptor extends MethodFilterInterceptor { private String name; public void setName(String name) { this.name = name; } @Override protected String doIntercept(ActionInvocation arg0) throws Exception { //取得被攔截的action LoginAction action = (LoginAction)arg0.getAction(); System.out.println(name+":攔截器的動作------"+"開始執行登錄action的時間為:"+new Date()); long start = System.currentTimeMillis(); String result = arg0.invoke(); System.out.println(name+":攔截器的動作------"+"執行完登錄action的時間為:"+new Date()); long end = System.currentTimeMillis(); System.out.println(name+":攔截器的動作------"+"執行完該action的時間為:"+(end-start)+"毫秒"); System.out.println(result); //輸出的值是:success return result; } }
至於jsp視圖,一樣,不需要改變。
得到的結果可以看出來:
當method="method1"或者是method="method3"的時候,會自動去執行MyMethodInterceptor 的方法doIntercept,然後跳轉到welcome.jsp界面。
當method="method2"的時候,控制台會出現 Action執行方法:method2(),之後便被攔截了。
以上就是攔截方法的基本代碼,例子很簡單,但是重在理解。
可能筆者疑惑,為什麼需要過濾方法呢?因為攔截器它會自動攔截所有的方法,回造成資源的損耗,所以有些方法我們可以指定不被攔截。
2.3、監聽過濾器:
在攔截器中,execute方法執行之前或者之後的方法都被攔截在intercept方法中,這些的結構不夠明白,我們可以定義監聽,雖然好像沒什麼用,但是瞭解一下也挺不錯的。
實現攔截器的監聽結果必須實現PreResultListener介面。
package com.Interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.PreResultListener; //過攔截器配置一個監聽器 public class MyPreResultListener implements PreResultListener { //定義處理Result之前的行為 @Override public void beforeResult(ActionInvocation arg0, String arg1) { System.out.println("返回的邏輯視圖為:"+arg1); } }
然後MyMethodInterceptor類修改為:
package com.Interceptor; import java.util.Date; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; //過濾方法 public class MyMethodInterceptor extends MethodFilterInterceptor { private String name; public void setName(String name) { this.name = name; } @Override protected String doIntercept(ActionInvocation arg0) throws Exception { //將一個攔截結果的監聽器註冊給攔截器 arg0.addPreResultListener(new MyPreResultListener()); System.out.println("execute方法被調用之前的攔截"); //調用下一個攔截器或者action的執行方法 String result = arg0.invoke(); System.out.println("execute方法被調用之後的攔截"); return result; } }
以上就是攔截器基本知識,如果有錯誤的地方,請指正。謝謝。