前言html
攔截器是Struts2框架的核心功能,理解並使用攔截器有助於更靈活使用Struts2。攔截器與Servlet中的過濾器有些相似卻又不盡相同。由於在Struts2中攔截器更像一個可插拔的組件,圍繞Action和Result進行,能夠在方法調用以前、以後使用。經過Struts2的工做流程(後面還會看到一個請求在Struts2中詳細的執行流程)能夠發現調用一個Action以前以後有許多的攔截器,這些攔截器都經過後才執行具體的action。對於每個攔截器來講,能夠直接返回,從而終止餘下的攔截器。java
從Struts2的工做流程提及apache
首先請看截取自官方的一張圖:瀏覽器
從圖中能夠看到,從一個具體的請求到Action須要通過多個攔截器,action處理完畢以後,後續的攔截器會繼續執行,最終到瀏覽器中。Struts2的工做流程以下:安全
從整個請求處理過程來看,攔截器是處理的關鍵。ok,經過以上請求處理過程,咱們知道了一個攔截器在Struts2中的工做方式。下面從編寫一個簡單的攔截開始,學習使用攔截器。markdown
一個簡單的攔截器session
主要有兩種方式:多線程
編寫本身的攔截器必須實現com.opensymphony.xwork2.interceptor.Interceptor接口,該接口有三個方法:init()、destroy()、intercept()。init方法在攔截器實例建立以後,intercept方法以前調用,主要用於初始化攔截器所須要的資源;destroy方法在攔截器實例銷燬以前調用,用於銷燬init初始化分配的資源;intercept方法則是在Action執行以前調用,能夠經過invocation對象獲取Action的狀態,從而根據狀態的不一樣進行須要的攔截操做。app
下面以實現Interceptor接口爲例,編寫一個計算Action執行execute方法的時間的攔截器。代碼以下:框架
package interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class TimeIntercptor implements Interceptor {
private static final long serialVersionUID = 1L;
@Override
public void destroy() {
}
@Override
public void init() {
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
long start = System.currentTimeMillis();
//執行action的execute方法
String result = invocation.invoke();
long end = System.currentTimeMillis();
System.out.println("執行execute方法的時間是" + (end - start));
return result;
}
}
在編寫一個action並在struts.xml配置文件中進行配置,在瀏覽器中進行測試就能夠獲得執行execute方法的具體時間了。在編寫攔截器類的時候須要注意:在攔截器中不該該有實例變量,由於攔截器是無狀態的,無狀態的解釋是若是攔截器有狀態,那麼在多線程同時訪問攔截器實例的時候,攔截器的狀態是不可預知的。
至此,咱們已經學會了如何編寫一個簡單的攔截器,下面介紹在攔截器中自帶的攔截器喲哪些。
Struts2中自帶的攔截器
自帶的攔截器能夠在struts-default.xml文件中獲得,主要有:
開發安全驗證功能的攔截器
在平常開發中,進行登陸驗證是很常見的。這裏開發的攔截器主要實現的功能是:若是用戶沒有登陸則提示沒有登陸的信息,並返回到登陸頁面。若是用戶已經登陸,則顯示資源。這裏主要介紹實際開發中攔截器的開發步驟。
步驟1:編寫基本頁面
登陸頁面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>登陸</title>
<s:head/>
</head>
</html>
<s:form action="login2">
<s:actionerror/>
<s:textfield label="用戶名" name="user.username"></s:textfield>
<s:password label="密碼" name="user.password"></s:password>
<s:submit value="登陸"></s:submit>
</s:form>
登陸成功頁面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>登陸 | 成功</title>
</head>
<body>
<h3>
<s:property value="user.username"/>,歡迎訪問struts2官方網站!
</h3>
</body>
</html>
資源頁面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>絕密資源</title>
</head>
<body>
<strong>這是絕密資源!</strong>
</body>
</html>
步驟二:編寫Action
LoginAction2.java:
package action;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import bean.User;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction2 extends ActionSupport implements SessionAware {
private static final long serialVersionUID = 1L;
private User user;
private Map<String, Object> session;
//經過login!input來訪問login.jsp
public String input() throws Exception{
return INPUT;
}
@Override
public String execute() throws Exception {
if("admin".equals(user.getUsername()) && "admin".equals(user.getPassword())){
System.out.println(user.getUsername()+"=" + user.getPassword());
session.put("user", user);
return SUCCESS;
}else{
addActionError("登陸失敗!");
return INPUT;
}
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
步驟四:編寫攔截器
代碼以下:
package interceptor;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class AuthenticationInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
/** * 對登陸與否進行攔截驗證 */
@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext context = ActionContext.getContext();
Map<String, Object> session = context.getSession();
Object user = session.get("user");
if(user == null){
//若是用戶未登陸,則返回登陸頁面,並添加錯誤信息
ActionSupport action = (ActionSupport) invocation.getAction();
action.addActionError("您尚未登陸,請先登陸!");
return action.LOGIN;
}else{
//若是用戶已經登陸,則執行後面的攔截器方法
return invocation.invoke();
}
}
}
步驟五:在struts.xml中進行配置
<interceptors>
<interceptor name="auth" class="interceptor.AuthenticationInterceptor" />
<interceptor-stack name="securityStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="auth" />
</interceptor-stack>
</interceptors>
<global-results>
<result name="login">/WEB-INF/pages/login.jsp</result>
</global-results>
<action name="login2" class="action.LoginAction2">
<result name="input">/WEB-INF/pages/login.jsp</result>
<result>/WEB-INF/pages/success.jsp</result>
</action>
對於受保護的資源引用上面的攔截器便可
<action name="resource" class="action.ResourceAction">
<result>/WEB-INF/pages/resource.jsp</result>
<interceptor-ref name="annotatedStack" />
</action>
步驟六:在瀏覽器中輸入http:localhost:8090/struts2/login2!input進行測試。
至此,一個安全驗證的攔截器就開發完畢。
攔截器小結
從開發過程能夠看待,攔截器的做用是Action的某個狀態進行攔截操做,使用攔截器能夠更方便處理業務邏輯。除了以上方式的開發攔截器外還有註解方式,不過註解方式的一個明顯缺點是不利於代碼的複用,並且註解的底層使用反射的方式完成的,因此使用註解開發,性能是一個值得考慮的問題。
以上內容轉載自https://blog.csdn.net/u011116672/article/details/50381656