zoukankan      html  css  js  c++  java
  • Struct2 拦截器

    拦截器的整个过程

    程序是在执行Action之前调用的拦截器,整个过程是这样子的

     

    这里面注意两个问题:

    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对象;

    so,在视图上拿valueStack对象的方式就有以下两种:

    1.request.getAttribute()

    2.ongl: #request.structs.valueStack

    第二个是循环Interceptor的问题,每一个Interceptor里面其实都调用了invoke方法,

    那么这个调用是怎么实现的呢,

    现在做一个模拟就明白了

    拦截器原理模拟

    使用最简单的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绑定上了,以后如果再换成其他架构基本上是无法实现的。

  • 相关阅读:
    新的工作开始
    昨日的世界
    【Drools-开源业务规则引擎】入门实例(含源码)
    【cs229-Lecture7】支持向量机(SVM)
    【2014年12月6日】HR交流会
    【cs229-Lecture5】生成学习算法:1)高斯判别分析(GDA);2)朴素贝叶斯(NB)
    【图算法】Dijkstra算法及变形
    【图算法】综述
    【云迁移论文笔记】A Comparison of On-premise to Cloud Migration Approaches
    【云迁移论文笔记】Cloud Migration Research:A Systematic Review
  • 原文地址:https://www.cnblogs.com/tech-bird/p/4160482.html
Copyright © 2011-2022 走看看