Java的Struts2框架中攔截器使用的實例教程
1、攔截器小介
攔截器的功能類似于web.xml文件中的Filter,能對用戶的請求進(jìn)行攔截,通過攔截用戶的請求來實現(xiàn)對頁面的控制。攔截器是在Struts-core-2.2.3.jar中進(jìn)行配置的,原始的攔截器是在struts-default.xml中配置的,里面封存了攔截器的基本使用方法。
Struts2攔截器功能類似于Servlet過濾器。在Action執(zhí)行execute方法前,Struts2會首先執(zhí)行struts.xml中引用的攔截器,如果有多個攔截器則會按照上下順序依次執(zhí)行,在執(zhí)行完所有的攔截器的interceptor方法后,會執(zhí)行Action的execute方法。
Struts2的攔截器必須從com.opensymphoy.xwork2.interceptor.Interceptor中實現(xiàn)該接口,在被定義的攔截器中有下面三個方法需要被實現(xiàn):
void destroy(); void init(); String intercept(ActionInvocation invocation) throws Exception;
自定義的攔截器需要重寫上面三個方法。另外Struts2的攔截器配置文件struts.xml它是繼承了原始文件struts-default.xml文件的,這樣在相應(yīng)的<package>中就會自動擁有struts-default.xml中的所有配置信息了。具體代碼如下:
<package name="demo" extends="struts-default" > ... </package>
2、添加攔截器
想要使用攔截器必須要經(jīng)過配置,struts2采用的是映射的方法,所以想用使用某一個功能就必須在配置文件中配置,攔截器也不例外。所以必須在package中添加相應(yīng)的攔截器元素,同時將攔截器關(guān)聯(lián)相應(yīng)的class文件,這樣在執(zhí)行action前才會執(zhí)行相應(yīng)的攔截器,具體使用方法如下。
(1)添加配置文件struts.xml,并在該文件中添加攔截器
<package name="testLogin" namespace="/" extends="struts-default">
<!-- 攔截器 -->
<interceptors>
<interceptor name="myInterceptor" class="com.interceptor.MyInterceptor"></interceptor>
</interceptors>
<action name="demo" class="com.action.LoginAction">
<result name="error" type="redirect">/error.jsp</result>
<result name="success">/success.jsp</result>
<result name="checkError">/checkSession.jsp</result>
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
上面的package中添加了一個名為myInterceptor的攔截器,并為該攔截器注冊了一個java類,該類名稱為MyInterceptor,并被封存在com.interceptor包中。另外還在該package中添加了相應(yīng)的action,在執(zhí)行該action前會首先執(zhí)行myInterceptor攔截器。
(2)編寫被注冊的攔截器類MyInterceptor,該類必須實現(xiàn)com.opensymphoy.xwork2.interceptor.Interceptor接口,并重寫相應(yīng)的方法
package com.interceptor;
import java.util.Map;
import com.entity.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("----destroy()----");
}
@Override
public void init() {
// TODO Auto-generated method stub
System.out.println("-----Init()-------");
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("----intercept()------");
Map<String, Object> session= invocation.getInvocationContext().getSession();
if(session.get("username")!=null){
System.out.println("登陸成功!");
//session.put("username",user.getUsername());
return invocation.invoke();
}else{
System.out.println("登陸失??!");
return "checkError";
}
}
}
(3)經(jīng)過前面兩步后,攔截器已經(jīng)配置完成,最后一部就是使用攔截器了,在顯示頁面上添加相應(yīng)的標(biāo)簽,并為標(biāo)簽指定上面創(chuàng)建的名為demo的action,然后執(zhí)行頁面即可在控制臺中打印出相應(yīng)的攔截器內(nèi)容。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<form action="demo">
用戶名:<input type="text" name="username"><br>
密 碼:<input type="text" name="password"><br>
<input type="submit" name="ok" value="提交">
</form>
</body>
</html>
打印輸出內(nèi)容:

分析輸出結(jié)果,程序編譯階段首先會去讀取配置文件struts.xml,在該配置文件action中順序查找是否添加了攔截器,如果添加了攔截器則根據(jù)攔截器名稱在<interceptors>中查找是否定義了該攔截器或者攔截器棧,如果發(fā)現(xiàn)定義的是攔截器則根據(jù)攔截器查找對應(yīng)的注冊的class,最后在包內(nèi)查找注冊的class并執(zhí)行相應(yīng)的init()方法;程序運行階段的大致流程和編譯階段類似,用戶在前臺提交請求后,會按照注冊的action在struts.xml中查找與之相對應(yīng)的,如果查找到將會查找攔截器,沒有查找到的話會相應(yīng)的拋錯,最后執(zhí)行攔截器注冊類的intercept方法。
3、攔截器棧
攔截器同樣有棧的概念,它是將使用的攔截器定義到共有的狀態(tài)下來實現(xiàn)統(tǒng)一管理,這樣在package中就可以做到攔截器的共享了,大大便利了攔截器的使用。在一個package中往往會用到重復(fù)的interceptor,如果每次都在Action中添加interceptor-ref的話就會很麻煩,那么攔截器棧就是為了解決這個問題而產(chǎn)生的,具體配置如下:
<package name="testLogin" namespace="/" extends="struts-default">
<!-- 攔截器 -->
<interceptors>
<interceptor name="myInterceptor" class="com.interceptor.MyInterceptor"></interceptor>
<!-- 定義公共的攔截器鏈,在action標(biāo)簽中只需要引用攔截器鏈 -->
<interceptor-stack name="defaultstack1">
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="demo" class="com.action.LoginAction">
<result name="error" type="redirect">/error.jsp</result>
<result name="success">/success.jsp</result>
<result name="checkError">/checkSession.jsp</result>
<interceptor-ref name="defaultstack1"></interceptor-ref>
</action>
</package>
實例中使用了interceptor-stack來定義了一個名稱為defaultstack1的攔截器棧,在該棧中添加了要執(zhí)行的攔截器,把攔截器做了封裝,在Action中直接調(diào)用該攔截器棧即可,實現(xiàn)了攔截器棧的共享。
4、默認(rèn)攔截器棧
另外可以定義默認(rèn)的攔截器棧,即:如果某個Action中沒有定義攔截器,那么它會默認(rèn)執(zhí)行該公共的攔截器。它和interceptors標(biāo)簽屬于同一等級的,使用default-interceptor-ref定義。
<package name="testLogin" namespace="/" extends="struts-default">
<!-- 攔截器 -->
<interceptors>
<interceptor name="myInterceptor" class="com.interceptor.MyInterceptor"></interceptor>
<!-- 定義公共的攔截器鏈,在action標(biāo)簽中只需要引用攔截器鏈 -->
<interceptor-stack name="defaultinter">
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定義默認(rèn)的攔截器棧,會自動注冊到action中 -->
<default-interceptor-ref name="defaultinter"></default-interceptor-ref>
<action name="demo" class="com.action.LoginAction">
<result name="error" type="redirect">/error.jsp</result>
<result name="success">/success.jsp</result>
<result name="checkError">/checkSession.jsp</result>
</action>
</package>
定義的默認(rèn)的攔截器棧只是在Action沒有指定攔截器的情況下才執(zhí)行自定義默認(rèn)的攔截器棧的,如果在Action中重定義了攔截器,那么它會覆蓋自定義默認(rèn)的攔截器棧的。
5、不執(zhí)行任何攔截器
還有一種情況是一個package中定義了默認(rèn)的攔截器,但是在編寫的某個Action中并不需要執(zhí)行任何攔截器,那么此時可以在相應(yīng)的Action中添加一個名稱為defaultStack的攔截器即可,它是系統(tǒng)默認(rèn)的攔截器,不會有任何操作。
<package name="testLogin" namespace="/" extends="struts-default">
<!-- 攔截器 -->
<interceptors>
<interceptor name="myInterceptor" class="com.interceptor.MyInterceptor"></interceptor>
<!-- 定義公共的攔截器鏈,在action標(biāo)簽中只需要引用攔截器鏈 -->
<interceptor-stack name="defaultinter">
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定義默認(rèn)的攔截器棧,會自動注冊到action中 -->
<default-interceptor-ref name="defaultinter"></default-interceptor-ref>
<action name="demo" class="com.action.LoginAction">
<result name="error" type="redirect">/error.jsp</result>
<result name="success">/success.jsp</result>
<result name="checkError">/checkSession.jsp</result>
<!-- 添加defaultStack保證不執(zhí)行攔截器 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
6、攔截方法
6.1 用法
上面的攔截器只是實現(xiàn)了對Action的攔截,其實攔截器的功能很強大,它也可以攔截相應(yīng)Action方法。和攔截Action不同的是想要攔截方法就必須繼承類MethodFilterInterceptor,該類封存在xwork-core.jar中,又一次證明了WebWork是Struts2的核心。另外還需要在配置文件中添加相應(yīng)的屬性來確定攔截的方法和不攔截的方法,具體配置方法如下:
<package name="testLogin" namespace="/" extends="struts-default">
<!-- 攔截器 -->
<interceptors>
<interceptor name="myInterceptor" class="com.interceptor.MyInterceptor"></interceptor>
<!-- 定義公共的攔截器鏈,在action標(biāo)簽中只需要引用攔截器鏈 -->
<interceptor-stack name="defaultinter">
<interceptor-ref name="myInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="demo" class="com.action.LoginAction">
<result name="error" type="redirect">/error.jsp</result>
<result name="success">/success.jsp</result>
<result name="checkError">/checkSession.jsp</result>
<!-- 在defaultStack中配置攔截方法,參數(shù)includeMethods中添加被攔截的方法名稱,excludeMethods中添加不需要攔截的名稱 -->
<interceptor-ref name="defaultStack">
<param name="includeMethods">添加要攔截的方法名稱</param><!-- 攔截方法 -->
<param name="excludeMethods">添加不需要攔截的方法名稱</param><!-- 不攔截方法 -->
</interceptor-ref>
</action>
</package>
繼承MethodFilterInterceptor類的相應(yīng)攔截方法的類中的代碼:
package com.interceptor;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class inter extends MethodFilterInterceptor {
@Override
public String doIntercept(ActionInvocation invocation) throws Exception {
System.out.println("--intercept()--");
//獲取相應(yīng)的Session
Map<String,Object> session=invocation.getInvocationContext().getSession();
Map request=(Map)ActionContext.getContext().get("request");
String username=(String)request.get("user.username");
if(session.get("username") != null){
String result=invocation.invoke();
System.out.println("--end()--");
return result;
}
}
}
6.2 Demo
來看一個攔截方法的實例,并對結(jié)果進(jìn)行分析。下面的實例演示攔截方法的輸出結(jié)果,在實例中分別創(chuàng)建了一個loginAction類,添加Action要執(zhí)行的方法;Inter類,攔截器中重寫MethodFilterInterceptor方法,在控制臺中輸出是否對某個方法進(jìn)行攔截;login.jsp文件,添加三個按鈕,分別演示三個方法的執(zhí)行。
(1)struts.xml內(nèi)方法攔截器的定義,在package中定義了一個名稱為inter的攔截器,在攔截器中指定了參數(shù),includeMethods用來攔截Method1,excludeMethods中的Method2表示不攔截Methods2方法,具體配置如下代碼:
<!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.action.extension" value=","></constant>
<package name="login" extends="struts-default">
<interceptors>
<interceptor name="inter" class="com.interceptor.inter">
<param name="includeMethods">Method1</param> <!-- 攔截Method1方法 -->
<param name="excludeMethods">Method2</param>
</interceptor>
<interceptor-stack name="myInterceptor">
<interceptor-ref name="inter"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="loginaction" class="com.action.loginAction">
<result name="success">success.jsp</result>
<result name="error">error.jsp</result>
<result name="cancel" type="redirectAction">Welcome</result>
<interceptor-ref name="inter"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
</struts>
(2)loginAction類,配置login.jsp中的action,分別在該類中添加Method1-Method3三個方法,其中Method1被攔截,Method2和Method3不被攔截,最后我們查看輸出結(jié)果。
package com.action;
import com.opensymphony.xwork2.ActionSupport;
public class loginAction extends ActionSupport {
@Override
public String execute() throws Exception {
if(this.username.equals("admin") && this.password.equals("admin")){
return "success";
}else if(this.username.equals("cancel") && this.password.equals("cancel")){
return "cancel";
}else{
return "error";
}
}
public void Method1(){
System.out.println("執(zhí)行方法:Method1");
}
public void Method2(){
System.out.println("執(zhí)行方法:Method2");
}
public void Method3(){
System.out.println("執(zhí)行方法:Method3");
}
private String username;
private String password;
public String getUsername(){
return this.username;
}
public void setUsername(String username){
this.username=username;
}
public String getPassword(){
return this.password;
}
public void setPassword(String password){
this.password=password;
}
}
(3)inter類,繼承MethodFilterInterceptor類,用來實現(xiàn)攔截方法。重寫doIntercept方法,在該方法中添加攔截的相應(yīng)信息。
package com.interceptor;
import java.util.Date;
import java.util.Map;
import com.action.loginAction;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class inter extends MethodFilterInterceptor {
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
System.out.println("攔截器在Action執(zhí)行前攔截"+new Date());
String result=invocation.invoke(); //執(zhí)行Action方法
System.out.println("攔截器在Action執(zhí)行后攔截"+new Date());
return result;
}
}
(4)login.jsp,在jsp頁面上添加三個按鈕,分別演示三個方法,判斷攔截器對方法的攔截情況。三個按鈕在點擊后回發(fā)的action是在javascript中動態(tài)的進(jìn)行添加的,這樣做達(dá)到了一個form中執(zhí)行不同的action的方法,當(dāng)然還有其它的方法,將會在下篇文章中討論。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>Insert title here</title>
<script type="text/javascript">
//方法1,定義被攔截的方法的實例
function method1(){
var form=document.forms[0];
form.action="loginaction!Method1";
form.submit();
}
//方法2,為按鈕2添加不攔截的方法
function method2(){
var form=document.forms[0];
form.action="loginaction!Method2";
form.submit();
}
//方法3,為按鈕3添加不攔截的方法
function method3(){
var form=document.forms[0];
form.action="loginaction!Method3";
form.submit();
}
</script>
</head>
<body>
<form>
用戶名:<input type="text" name="username"><br>
密 碼:<input type="text" name="password"><br>
<input type="submit" name="ok" value="按鈕1" onclick="method1()">
<input type="submit" name="ok1" value="按鈕2" onclick="method2()">
<input type="submit" name="ok2" value="按鈕3" onclick="method3()">
</form>
</body>
</html>
運行完成后的頁面視圖:

(5)分析運行結(jié)果,分別單擊按鈕1、2、3,在控制臺中輸出結(jié)果,按鈕1是綁定的method1,該方法在struts.xml中進(jìn)行了攔截如果結(jié)果正確的話會顯示被攔截的結(jié)果,而相應(yīng)的按鈕2和3只輸出運行結(jié)果,因為它們沒有被攔截。那看下面的結(jié)果圖:

結(jié)果圖正好正是了我們的分析結(jié)果,按鈕1被攔截了,執(zhí)行了inter類中的doIntercept方法,二相應(yīng)的按鈕2和3沒有被攔截。也就是說,Method1被放到了方法攔截器的白名單內(nèi),執(zhí)行要攔截該方法;Method2被放到了攔截器黑名單內(nèi),不需要攔截該方法;Method3不做任何處理。
7、結(jié)語
對于攔截器的內(nèi)容就總結(jié)到這里,攔截器提供了很強大的功能,使得開發(fā)人員能夠在運行時控制輸出結(jié)果,增加了編程的靈活性。另外對于任何理論性的東西都不要試圖去記憶,一定要理性的去分析,多多實踐,動手做幾個實例,分析結(jié)果更深刻的理解。
PS:Struts2(XWork)提供的攔截器的功能說明
|
攔截器 |
名字 |
說明 |
|
Alias Interceptor |
alias |
在不同請求之間將請求參數(shù)在不同名字件轉(zhuǎn)換,請求內(nèi)容不變 |
|
Chaining Interceptor |
chain |
讓前一個Action的屬性可以被后一個Action訪問,現(xiàn)在和chain類型的result(<result type=”chain”>)結(jié)合使用。 |
|
Checkbox Interceptor |
checkbox |
添加了checkbox自動處理代碼,將沒有選中的checkbox的內(nèi)容設(shè)定為false,而html默認(rèn)情況下不提交沒有選中的checkbox。 |
|
Cookies Interceptor |
cookies |
使用配置的name,value來是指cookies |
|
Conversion Error Interceptor |
conversionError |
將錯誤從ActionContext中添加到Action的屬性字段中。 |
|
Create Session Interceptor |
createSession |
自動的創(chuàng)建HttpSession,用來為需要使用到HttpSession的攔截器服務(wù)。 |
|
Debugging Interceptor |
debugging |
提供不同的調(diào)試用的頁面來展現(xiàn)內(nèi)部的數(shù)據(jù)狀況。 |
|
Execute and Wait Interceptor |
execAndWait |
在后臺執(zhí)行Action,同時將用戶帶到一個中間的等待頁面。 |
|
Exception Interceptor |
exception |
將異常定位到一個畫面 |
|
File Upload Interceptor |
fileUpload |
提供文件上傳功能 |
|
I18n Interceptor |
i18n |
記錄用戶選擇的locale |
|
Logger Interceptor |
logger |
輸出Action的名字 |
|
Message Store Interceptor |
store |
存儲或者訪問實現(xiàn)ValidationAware接口的Action類出現(xiàn)的消息,錯誤,字段錯誤等。 |
|
Model Driven Interceptor |
model-driven |
如果一個類實現(xiàn)了ModelDriven,將getModel得到的結(jié)果放在Value Stack中。 |
|
Scoped Model Driven |
scoped-model-driven |
如果一個Action實現(xiàn)了ScopedModelDriven,則這個攔截器會從相應(yīng)的Scope中取出model調(diào)用Action的setModel方法將其放入Action內(nèi)部。 |
|
Parameters Interceptor |
params |
將請求中的參數(shù)設(shè)置到Action中去。 |
|
Prepare Interceptor |
prepare |
如果Acton實現(xiàn)了Preparable,則該攔截器調(diào)用Action類的prepare方法。 |
|
Scope Interceptor |
scope |
將Action狀態(tài)存入session和application的簡單方法。 |
|
Servlet Config Interceptor |
servletConfig |
提供訪問HttpServletRequest和HttpServletResponse的方法,以Map的方式訪問。 |
|
Static Parameters Interceptor |
staticParams |
從struts.xml文件中將<action>中的<param>中的內(nèi)容設(shè)置到對應(yīng)的Action中。 |
|
Roles Interceptor |
roles |
確定用戶是否具有JAAS指定的Role,否則不予執(zhí)行。 |
|
Timer Interceptor |
timer |
輸出Action執(zhí)行的時間 |
|
Token Interceptor |
token |
通過Token來避免雙擊 |
|
Token Session Interceptor |
tokenSession |
和Token Interceptor一樣,不過雙擊的時候把請求的數(shù)據(jù)存儲在Session中 |
|
Validation Interceptor |
validation |
使用action-validation.xml文件中定義的內(nèi)容校驗提交的數(shù)據(jù)。 |
|
Workflow Interceptor |
workflow |
調(diào)用Action的validate方法,一旦有錯誤返回,重新定位到INPUT畫面 |
|
Parameter Filter Interceptor |
N/A |
從參數(shù)列表中刪除不必要的參數(shù) |
|
Profiling Interceptor |
profiling |
通過參數(shù)激活profile |
相關(guān)文章
httpclient 請求http數(shù)據(jù),json轉(zhuǎn)map的實例
下面小編就為大家?guī)硪黄猦ttpclient 請求http數(shù)據(jù),json轉(zhuǎn)map的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
淺談Java中Lambda表達(dá)式的相關(guān)操作
java8新特性,Lambda是一個匿名函數(shù),類似Python中的Lambda表達(dá)式、js中的箭頭函數(shù),目的簡化操作,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
Mybatis的mapper.xml中if標(biāo)簽test判斷的用法說明
這篇文章主要介紹了Mybatis的mapper.xml中if標(biāo)簽test判斷的用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
SpringBoot整合SpringSecurity實現(xiàn)權(quán)限控制之實現(xiàn)多標(biāo)簽頁
這篇文章主要介紹了SpringBoot整合SpringSecurity實現(xiàn)權(quán)限控制之實現(xiàn)多標(biāo)簽頁,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-11-11

