1.Struts2架构图

2.Struts2 执行过程分析

  1.首先,因为使用 struts2 框架,请求被Struts2Filter 拦截

  2.Struts2Filter  调用 DisPatcher 的 serviceAction 方法

  3.在serviceAction 中,创建 ActionProxy对象,并调用其execute方法

  4.在ActionProxy的execute中,调用ActionInvocation的invoke方法,ActionInvocation对象中包含了众多的拦截器(ExceptionInterceptor等)

  5.ActionInvocation的invoke方法 会调用这些拦截器的intercept方法,

   每一个intercept方法都会回过头调用之前的ActionInvocation对象的invoke方法

  6.再次调用这个invkoe,会继续调用下一个拦截器,直到所有的拦截器都被调用一遍后,没有下一个拦截器了,此时就会调用Action的execute方法了

  7.调用了Action中的方法后,此时最后一个拦截器的invoke方法完成调用,

   最后一个拦截器执行invoke方法之后的代码,然后一直迭代回去,第一个拦截器的invoke方法也调用完毕

  8.所有的拦截器的intercept方法 结束后,ActionInvocation的invoke方法也结束,最后形成响应回去

 注:类似于 Filter 拦截WEB资源时的这种关系,doFileter方法和chain方法

 调用chain方法时,会先看下后面是否还有Filter注册了,如果有,先执行后面Filter的 doFileter方法,等到判断到后面没有Filter了,

 最后一个Filter的chain方法才能被执行,最后一个Filter全部都执行完成之后,才会回调之前的Filter

 /*这种形式也有点类似AOP的感觉,一个又一个的拦截器,就是一个又一个的切面*/

3.Interceptor 拦截过程模拟

 public class ActionInvocation {
List<Interceptor> interceptors = new ArrayList<Interceptor>();
Action a = new Action();
int index = -1; public ActionInvocation() {
this.interceptors.add(new FirstInterceptor());
this.interceptors.add(new SecondInterceptor());
} public void invoke() {
index++;
if(index >= this.interceptors.size()) {
a.execute();
}
else {
this.interceptors.get(index).interceptor(this);
}
} }

4.定义自己的拦截器(一般没有必要去定义自己的拦截器,常见的拦截器通常已经做好了)

  1.编写拦截器(实现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 arg0) throws Exception {
long t1 = System.currentTimeMillis();
String r = arg0.invoke();
long t2 = System.currentTimeMillis();
System.out.println("time="+(t2-t1));
return r;
} }

  2.在struts.xml中注册(使用 interceptors标签 声明拦截器)<interceptor-ref>(使用这个拦截器)

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

5.使用token拦截器(防止表单重复提交)(很少用 有其他方式)

  1.在form 表单中添加<s:token></s:token> (作用,生成一个唯一的识别码,用于验证是否重复提交)

  2.在struts.xml中添加 <result name="invalid.token">/error.jsp</result> (至于为什么是 'invalid.token',可以查看struts-default.xml)

                <interceptor-ref name="token"></interceptor-ref>

过程:1.使用token拦截器 会在服务器端生成一个 唯一标识码
   2.客户端通过 <s:token></s:token> 发送 标识码过来 和服务器端的进行对比,对比完成后,这个唯一标识码会删除,
     重复提交时,客户端再发送 标识码 ,服务端已经没有了,返回结果 'invalid.token'

6.认识默认的拦截器(servletConfig)

作用:取得Map类型request,session,application 等

1.在Action中,让Action实现RequestAware,SessionAware,ApplicationAware 这种接口,

2.实现这些接口,需要重写一些方法,如setRequest(Map<String, Object> request)

这个过程的实现,就是通过  ServletConfigInterceptor  这个拦截器 实现的

7.类型转换

  1.默认转换

    (将前台提交的String 类型的数据 转换成如int,List,Set(interests=math&interests=history),

     数组,Map(users['a']=usera&users['b']=userb))

    如果想转换成日期类型,需符合输入规范,也可以通过<s:date> 标签用指定的格式显示 日期

    http://localhost:8080/struts2_37_type_conversion/test?name=xzk&age=21&d=1996-07-29&interests=math&interests=history&users[%27a%27]=usera&users[%27b%27]=userb

  2.写自己的转换器

 public class MyPointConverter extends StrutsTypeConverter{

     @Override
public Object convertFromString(Map context, String[] values, Class toClass) { Point p = new Point();
String[] strs = (String[])values;
String[] xy = strs[0].split(",");
p.x = Integer.parseInt(xy[0]);
p.y = Integer.parseInt(xy[1]);
return p;
} @Override
public String convertToString(Map context, Object o) {
// TODO Auto-generated method stub
return o.toString();
} }

  3.三种注册方式(写好自己的转换器后,还需要完成注册)

    a) 局部(将注册文件(XXXAction-conversion.properties)放到和Action同级下)

    b) 全局:xwork-conversion.properties

       java.awt.Point=com.bjsxt.converter.MyPointConverter

    c) Annotation (注解)

http://localhost:8080/struts2_37_type_conversion/test?p=2,3&ps=2,3&ps=3,4&points[%27a%27]=2,3&points[%27b%27]=3,4

7.Struts2拦截器及源码分析的更多相关文章

  1. Mybatis Interceptor 拦截器原理 源码分析

    Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最 ...

  2. SpringBoot拦截器及源码分析

    1.拦截器是什么 java里的拦截器(Interceptor)是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止 ...

  3. Struts2请求处理流程及源码分析

    1.1 Struts2请求处理 1. 一个请求在Struts2框架中的处理步骤: a) 客户端初始化一个指向Servlet容器的请求: b) 根据Web.xml配置,请求首先经过ActionConte ...

  4. concurrent(六)同步辅助器CyclicBarrier & 源码分析

    参考文档:Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例:https://www.cnblogs.com/skywang12345/p/3533995.html简介Cy ...

  5. concurrent(五)同步辅助器CountDownLatch & 源码分析

    参考文档: https://blog.csdn.net/zxdfc/article/details/52752803 简介 CountDownLatch是一个同步辅助类.允许一个或多个线程等待其他线程 ...

  6. scrapy-redis(调度器Scheduler源码分析)

    settings里面的配置:'''当下面配置了这个(scrapy-redis)时候,下面的调度器已经配置在scrapy-redis里面了'''##########连接配置######## REDIS_ ...

  7. springmvc(3)拦截器HandlerInterceptor源码的简单解析

    其实拦截器就是我们的AOP编程.拦截器在我们的实际项目中实用性比较大的,比如:日志记录,权限过滤,身份验证,性能监控等等.下面就简单的来研究一下拦截器: public interface Handle ...

  8. storm事件管理器EventManager源码分析-event.clj

    storm事件管理器定义在event.clj中,主要功能就是通过独立线程执行"事件处理函数".我们可以将"事件处理函数"添加到EventManager的阻塞队列 ...

  9. struts2拦截器源码分析

    前面博客我们介绍了开发struts2应用程序的基本流程(开发一个struts2的实例),通过前面我们知道了struts2实现请求转发和配置文件加载都是拦截器进行的操作,这也就是为什么我们要在web.x ...

随机推荐

  1. hibernate对连接池的支持

    连接池, 作用: 管理连接:提升连接的利用效率! 常用的连接池: C3P0连接池   Hibernate 自带的也有一个连接池,且对C3P0连接池也有支持!   Hbm 自带连接池:          ...

  2. Hibernate3映射数据类型

    1. 在实际开发中需要在hbm文件中使用的type属性值是指定的类型.那    么指定的类型一般的是基于hibernate的类型.2. 当然在实际过程中也可以在hbm文件中指定java类型. publ ...

  3. egg源码浅析一npm init egg --type=simple

    要egg文档最开始的时候,有这样的几条命令: 我们推荐直接使用脚手架,只需几条简单指令,即可快速生成项目: $ mkdir egg-example && cd egg-example ...

  4. Maven exclusions(排除依赖)

    在写pom的时候,我们写的一个依赖往往会依赖于其他的包,而这些包可能是过时的不安全的,因此需要排除并重新引用安全的版本,先在依赖这个项目的pom中去除想排除的依赖,再添加指定版本的依赖. pom的依赖 ...

  5. grep 正则表达式用引号括起来和元字符加反斜杠转义的测试

    grep 正则表达式用引号括起来和元字符加反斜杠转义的测试 实验在 grep 命令中的表达式:不加引号,加单引号,加双引号的区别,以及部分元字符前加与不加 `\’ 进行转义的区别.实验环境为“实验楼( ...

  6. Linux任务后台运行的方法

    linux在后台运行程序当我们在终端或控制台工作时,可能不希望由于运行一个作业而占住了屏幕,因为可能还有更重要的事情要做,比如阅读电子邮件.对于密集访问磁盘的进程,我们更希望它能够在每天的非负荷高峰时 ...

  7. 如何写出优雅耐看的JavaScript代码

    参考链接:https://segmentfault.com/a/1190000020444918?utm_medium=hao.caibaojian.com&utm_source=hao.ca ...

  8. 论文阅读及复现 | Effective Neural Solution for Multi-Criteria Word Segmentation

    主要思想 这篇文章主要是利用多个标准进行中文分词,和之前复旦的那篇文章比,它的方法更简洁,不需要复杂的结构,但比之前的方法更有效. 方法 堆叠的LSTM,最上层是CRF. 最底层是字符集的Bi-LST ...

  9. python装饰器使用详解

    装饰器 '''装饰器:就是闭包(闭包的一个应用场景) -- 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数 优点: -- 丰富了原有函数的功能 -- 提高了程序的可拓展性''' 开 ...

  10. shell sed 替代1

    sed -e '/-DLUA_USE_LINUX/s/-lreadline/-lreadline -lncurses/g' Makefile > tmp mv tmp Makefile 全局换- ...