struts入門四之攔截器

前言html

攔截器是Struts2框架的核心功能,理解並使用攔截器有助於更靈活使用Struts2。攔截器與Servlet中的過濾器有些相似卻又不盡相同。由於在Struts2中攔截器更像一個可插拔的組件,圍繞Action和Result進行,能夠在方法調用以前、以後使用。經過Struts2的工做流程(後面還會看到一個請求在Struts2中詳細的執行流程)能夠發現調用一個Action以前以後有許多的攔截器,這些攔截器都經過後才執行具體的action。對於每個攔截器來講,能夠直接返回,從而終止餘下的攔截器。java

從Struts2的工做流程提及apache

首先請看截取自官方的一張圖:瀏覽器

struts2工做流程

從圖中能夠看到,從一個具體的請求到Action須要通過多個攔截器,action處理完畢以後,後續的攔截器會繼續執行,最終到瀏覽器中。Struts2的工做流程以下:安全

  1. 請求發送給StrutsPrepareAndExecuteFilter
  2. StrutsPrepareAndExecuteFilter判斷該請求是不是一個Struts2請求,若是是則進入第3步
  3. 若是是Struts2請求,則把請求交給ActionProxy,是Action的代理類
  4. ActionProxy建立一個ActionInvocation實例,並進行初始化
  5. 在執行具體的Action以前,ActionProxy會涉及相關攔截器的調用
  6. Action調用結束以後,會根據struts.xml文件中action的result配置對象獲得對應的返回結果。調用execute方法以後,對返回結果進行渲染
  7. 執行後面的攔截器
  8. 把結果返回給瀏覽器

從整個請求處理過程來看,攔截器是處理的關鍵。ok,經過以上請求處理過程,咱們知道了一個攔截器在Struts2中的工做方式。下面從編寫一個簡單的攔截開始,學習使用攔截器。markdown

一個簡單的攔截器session

主要有兩種方式:多線程

  • 實現Interceptor接口
  • 繼承AbstractInterceptor抽象類

編寫本身的攔截器必須實現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文件中獲得,主要有:

  • execAndWait(該攔截器可讓須要運行較長時間的action在後臺運行,並向用戶顯示進度信息)
  • exception(主要用於異常處理)
  • fileUpload(用於文件上傳)
  • i18n(國際化的支持)
  • logger(日誌,記錄action的開始於結束日誌)
  • modelDriven(支持模型驅動的攔截器)
  • validation(定義本身的驗證器)

開發安全驗證功能的攔截器

在平常開發中,進行登陸驗證是很常見的。這裏開發的攔截器主要實現的功能是:若是用戶沒有登陸則提示沒有登陸的信息,並返回到登陸頁面。若是用戶已經登陸,則顯示資源。這裏主要介紹實際開發中攔截器的開發步驟。

步驟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

相關文章
相關標籤/搜索