Struct2 攔截器

 

 

攔截器的整個過程java

 

程序是在執行Action以前調用的攔截器,整個過程是這樣子的spring

 

 

這裏面注意兩個問題:編程

 

public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
                              ActionMapping mapping) throws ServletException {

        Map<String, Object> extraContext = createContextMap(request, response, mapping, context);

        // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
try {
           
            Configuration config = configurationManager.getConfiguration();
            ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                    namespace, name, method, extraContext, true, false);

            request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
這個字段就是"struts.valueStack"
// if the ActionMapping says to go straight to a result, do it!
            if (mapping.getResult() != null) {
             
            } else {
                proxy.execute();
            }

          
        } catch (ConfigurationException e) {        
      
    }

 

就看裏面標記的這幾句,這個方法的做用設置好valueStack,而後放到request範圍裏服務器

也就是說經過request能夠獲得valueStack對象;session

so,在視圖上拿valueStack對象的方式就有如下兩種:架構

1.request.getAttribute()app

2.ongl: #request.structs.valueStackjsp

 

 

第二個是循環Interceptor的問題,每個Interceptor裏面其實都調用了invoke方法,this

那麼這個調用是怎麼實現的呢,spa

如今作一個模擬就明白了

攔截器原理模擬

 

使用最簡單的java工程作實驗

 

 

而後定義一個Action,表示最後要執行的東東

public class Action {
    public void execute() { System.out.println("execute!"); } }

 

而後最重要的是定義一個ActionInvocation 

import java.util.ArrayList;
import java.util.List;


public class ActionInvocation {
    List<Interceptor> interceptors = new ArrayList<Interceptor>();
    int index = -1;
    Action a = new Action();
    
    public ActionInvocation() {
        this.interceptors.add(new FirstInterceptor());
        this.interceptors.add(new SecondInterceptor());        
    }

//首先遍歷每個攔截器,當遍歷完了以後,執行Action的方法
public void invoke() { index ++; if(index >= this.interceptors.size()) { a.execute(); }else { this.interceptors.get(index).intercept(this); } } }

 

先定義一個接口,至關於攔截器

public interface Interceptor {
    public void intercept(ActionInvocation invocation) ;
}

而後兩個類實現這個接口

public class FirstInterceptor implements Interceptor {

    public void intercept(ActionInvocation invocation) {
        System.out.println(1);
//在裏面又返回調用ActionInvocation 的Invoke方法 invocation.invoke(); System.out.println(
-1); } }
public class SecondInterceptor implements Interceptor {

    public void intercept(ActionInvocation invocation) {
        System.out.println(2);
        invocation.invoke();
        System.out.println(-2);
    }
}

 

 

定義主方法

public class Main {
    public static void main(String[] args) {
        new ActionInvocation().invoke();
    }
}

 

最後的結果是

1
2
execute!
-2
-1

      這裏面最關鍵的地方就是轉來轉去用的都是同一個ActionInvocation 對象

流程大概是:

    實線表示直接調用,虛線表示方法返回

   上圖是完整的調用過程

    由於ActionInvocation調用Second是在First內部,只是轉折了一下,因此能夠理解爲First調用了Second

 

 

 經過Struct官方的圖來理解整個過程

 

 

 

 

    最主要的思想是在執行Action以前攔一下,在執行以後攔一下

 

從這個圖中,也能夠理解什麼叫作AOP,面向切面編程

原本有沒有攔截器Struct方法都能執行

可是忽然冒出一個攔截器有種在執行以前切上一刀的感受

攔截器的有點是可插入,可抽回

 

攔截器能夠用在敏感字符處理,在提交的數據進入服務器的時候,首先檢查數據是否是有敏感字符

還能夠用在權限上面

 

咱們想一下若是沒有攔截器怎麼作權限

有兩種方式:

一個是在Action類中的exection方法裏面進行判斷

一個是在Jsp的頭的session裏面進行判斷

這樣作是要在每個Action和JSP裏面都要寫的啊

 

固然權限判斷如今有很好的spring security

 

 

 

定義本身的Struct攔截器

 

這個其實就是重複形成輪子的過程,只要看看別人的輪子是怎麼造出來的就能夠了。

 

首先:定義一個MyInterceptor類

package com.bjsxt.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class MyInterceptor implements Interceptor {

    public void destroy() {
        // TODO Auto-generated method stub
        
    }

    public void init() {
        // TODO Auto-generated method stub
        
    }

    public String intercept(ActionInvocation invocation) throws Exception {
        long start = System.currentTimeMillis();
        String r = invocation.invoke();
        long end = System.currentTimeMillis();
        System.out.println("action time = " + (end - start));
        return r;
    }

}

 

而後要把這個攔截器加到配置裏面

在Struct裏面,默認攔截器都是放在/struts-default.xml 裏面,固然咱們不能改人家的代碼。

 

修改Struct.xml

    <package name="test" namespace="/" extends="struts-default">

首先聲明這個攔截器
<interceptors> <interceptor name="my" class="com.bjsxt.interceptor.MyInterceptor"></interceptor> </interceptors> <action name="test" class="com.bjsxt.action.TestAction"> <result>/test.jsp</result> <interceptor-ref name="my"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> </package>

 

       在實際開發過程當中,自定義攔截器其實是不多不多用到的。一方面,Struct已經爲咱們寫出來不少攔截器,另外一方面,一旦咱們自定義了攔截器,那麼咱們的代碼就和Struct綁定上了,之後若是再換成其餘架構基本上是沒法實現的。

相關文章
相關標籤/搜索