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绑定上了,之后若是再换成其余架构基本上是没法实现的。

相关文章
相关标签/搜索