Struts2的核心在于它复杂的拦截器,几乎70%的工作都是由拦截器完成的。比如我们之前用于将上传的文件对应于action实例中的三个属性的fileUpload拦截器,还有用于将表单页面的http请求参数设置成action中对应的属性的param拦截器等。总之,在整个Struts框架中拦截器的作用是相当大的,本篇将从以下几点详细介绍下有关Struts拦截器的内容:

  • 拦截器在Struts中的作用
  • 自定义拦截器实现类
  • 配置拦截器(包含配置默认拦截器)
  • 引用拦截器
  • 配置拦截指定方法的拦截器
  • 拦截器的拦截顺序

一、拦截器在Struts中的作用
     在我们的web.xml中,我们配置了一个过滤器,实现将所有请求交付StrutsPrepareAndExecuteFilter类。一旦接受到任意action的请求,该类会创建和初始化一个ActionProxy实例,它代理了具体的action,在其中我们可以添加任意拦截器在execute方法执行之前和之后做一些额外的操作,最终会调用该action实例的execute方法,为用户返回视图结果字符串,然后系统会根据该视图结果字符串调取相应的视图页面。下图是拦截器和action之间的关系:

这是一种典型的AOP思想,当我们在Struts.xml中定义一个包的时候,大部分情况下我们会继承struts-default文件,所以虽然我们在自己的配置文件中并没有手动配置任何的拦截器,但是我们创建的action却被很多拦截器拦截处理,就是因为struts-default中配置的拦截器生效了。Struts中内建了很多的拦截器,他们大多被配置在struts-default文件中,详细的内建拦截器的介绍可以参考官方API,接下来我们看如何自定义一个拦截器。

二、自定义拦截器实现类
     想要实现自己的拦截器类只需要实现 com.opensymphony.xwork2.interceptor.Interceptor.Interceptor 接口即可,该接口中有如下几个方法:

  public abstract void destroy();public abstract void init();public abstract String intercept(ActionInvocation paramActionInvocation)throws Exception;

init 方法在执行拦截方法之前回调,主要用于初始化一些资源,destroy 与init 方法对应,在拦截器实例被销毁之前回调,主要用于释放在init 方法中打开的资源。intercept 方法是我们的拦截方法,我们可以重写该方法来完成对action实例的拦截,该方法具有一个ActionInvocation 类型的参数,该参数内部引用了具体的action实例对象(如果该action还有其他拦截器的话),我们可以调用该参数的invoke方法调用具体action实例的execute方法或者调用下一个拦截器,intercept方法返回一个String 类型的字符串代表了具体视图页面。下面看个具体的例子:

public class TestAction extends ActionSupport {public String execute(){System.out.println("执行execute方法......");return SUCCESS;}
}
public class MyIntercept implements Interceptor {public void init() {}public void destroy() {}public String intercept(ActionInvocation action) throws Exception{System.out.println("拦截action开始.......");String result = action.invoke();System.out.println("拦截action结束.......");return result;}
}

省略了配置拦截器和TestAction 的代码,下图是上述程序运行的结果截图:

三、配置和引用拦截器
     上述的示例定义了一个简单的拦截器实现类,我们省略了在struts.xml中配置和引用该拦截器的代码,本小节将详细的介绍如何在struts.xml中定义和引用我们自定义实现的拦截器类。

从struts-default.xml中我们可以看出来,我们使用<interceptors>元素定义拦截器name和物理位置的配对,例如:

<interceptors><interceptor name="test" class="MyPackage.TestAction"/>............
</interceptors>

上述代码定义了一个拦截器test,它对应于具体的一个class。需要注意的是,定义拦截器的元素 interceptors 及其子元素必须被配置在某个package包下。

以上只是定义了一个拦截器和具体拦截器实现类之间的映射关系,但是想要实现对某个具体的action的拦截需要使用元素<interceptor-ref>根据name属性值引用一个上述已经定义了的拦截器。例如:

<action name="test" class="MyPackage.TestAction"><interceptor-ref name="test"/><result name="success">/index.jsp</result>............
</action>

正如上述代码展示的一样,该元素用于引用一个已经定义好了的拦截器,并且该元素出现在具体的action内部,表明了该action具有一个test拦截器。以上代码实现了对单个拦截器的定义和引用,其实对于拦截器栈(一堆拦截器的组合)来说配置也是类似的。定义一个拦截器栈的代码是如下的:

<interceptor-stack name="拦截器栈名">interceptor-ref name="拦截器一"/>interceptor-ref name="拦截器二"/>interceptor-ref name="拦截器三"/>.....
</interceptor-stack>

引用一个拦截器栈就没什么区别了:

interceptor-ref name="拦截器栈名"/>

当然我们也可以通过

<default-interceptor-ref name="拦截器名"/>

配置默认拦截器或者拦截器栈,如果该包下某个action没有显式指定拦截器,那么就会调用该默认拦截器,否则如果显式配置了拦截器,那么默认拦截器将会失效。

四、为Action中指定方法配置拦截器
     在默认情况下,我们为action配置了拦截器之后,该拦截器将会拦截该action中所有的方法,这有时候会给我们带来麻烦,当然struts为我们提供API用来针对具体的某个方法配置拦截器。这里涉及到一个抽象类:MethodFilterInterceptor。该类实际上实现了Interceptor并完成了一些默认实现,我们简单看看其中的代码:

public abstract class MethodFilterInterceptorextends AbstractInterceptor
{//该set集合保存了该拦截器不需要拦截的所有方法protected Set<String> excludeMethods = Collections.emptySet();//该set集合保存了所有该拦截器需要拦截的方法protected Set<String> includeMethods = Collections.emptySet();//省略getter,setter方法//用于拦截action的入口public String intercept(ActionInvocation invocation)throws Exception{if (applyInterceptor(invocation)) {return doIntercept(invocation);}return invocation.invoke();}//判断当前需要调用的action处理逻辑方法是否需要被此拦截器拦截protected boolean applyInterceptor(ActionInvocation invocation){String method = invocation.getProxy().getMethod();boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(this.excludeMethods, this.includeMethods, method);if ((this.log.isDebugEnabled()) && (!applyMethod)) {this.log.debug("Skipping Interceptor... Method [" + method + "] found in exclude list.", new String[0]);}return applyMethod;}//这是需要我们重写的方法,具体作用下文介绍protected abstract String doIntercept(ActionInvocation paramActionInvocation)throws Exception;
}

从上述代码中可以看出,该抽象类实现了Interceptor接口并完成了基本的实现。除此之外,该类提供了两个集合用于保存该拦截器需要拦截的所有方法和不需要拦截的所有方法,拦截器入口intercept中会首先判断此次请求action实例中的逻辑处理方法是否需要被该拦截器拦截,如果需要被拦截,那么将会调用doIntercept我们自己实现的拦截器逻辑。否则直接调用invoke方法执行处理逻辑。所以一般来说,我们只需要重写doIntercept方法完成拦截器的核心处理即可。

当然此处需要注意一点的是,用于判断当前请求的处理逻辑方法是否需要被该拦截器拦截的方法applyInterceptor是在intercept中进行校验的,也就是说在执行doIntercept方法之前excludeMethods和includeMethods的值应当是已经初始化完毕了的。所以我们在doIntercept中再次为这两个属性赋值是没用的,因为已经完成了校验。一般我们在struts.xml中为这两个属性赋值,因为该配置文件是先被加载的。下面我们看个实例:

//自定义一个拦截器
public class MyIntercept extends MethodFilterInterceptor {protected  String doIntercept(ActionInvocation action)throws Exception{System.out.println("拦截开始......");String result = action.invoke();System.out.println("拦截结束......");return result;}
}
//引用该拦截器并指定不需要拦截的方法
<action name="test" class="MyPackage.TestAction"><interceptor-ref name="test"><param name="excludeMethods">execute</param></interceptor-ref><result name="success">/index.jsp</result>
</action>

下面我们看运行的结果截图:

显然我们指明了该拦截器不用拦截方法execute,当然结果显示的也是如我们所愿。如果我们修改上述struts.xml中内容:

<action name="test" class="MyPackage.TestAction"><interceptor-ref name="test"><param name="includeMethods">execute</param></interceptor-ref><result name="success">/index.jsp</result>
</action>

我们指定该execute方法是需要被拦截器拦截的,下面运行的结果截图:

当然如果需要指定多个方法需要被拦截或者不用被拦截,可以使用英文逗号隔开这些方法,例如:

<param name="includeMethods">方法一,方法二,方法三</param>

最后还有一点是:如果一个方法既被放在了includeMethods中也被放在了excludeMethods中,那么框架将会选择拦截该方法。

五、有关拦截器机制的其他一些细节
     拦截器的执行顺序是按照引用拦截器的顺序决定的,例如我们定义两个拦截器:

<action name="test" class="MyPackage.TestAction"><interceptor-ref name="test"/><interceptor-ref name="test2"/><result name="success">/index.jsp</result>
</action>

也就是说第一个拦截器拦截action之后,会调用invoke方法,如果还有其他拦截器则会调用下一个拦截器,一层层嵌套,最后结束最外层的拦截器。

上述实例中我们使用param参数为拦截器类中的includeMethods属性赋值,但是如果是一个拦截器栈中我们有该如何为其中某个具体的拦截器属性赋值呢?

<interceptor-ref name="拦截器栈"><param name="拦截器一.属性名">属性值</param>
</interceptor-ref>

至此,我们简单了解了有关struts2中拦截器器的相关知识,如需深刻理解还要在具体项目中体会,总结不到之处,望海涵!

详解Struts2拦截器机制相关推荐

  1. OkHttp3源码详解(三) 拦截器-RetryAndFollowUpInterceptor

    最大恢复追逐次数: private static final int MAX_FOLLOW_UPS = 20; 处理的业务: 实例化StreamAllocation,初始化一个Socket连接对象,获 ...

  2. Struts2拦截器的使用 (详解)

    Struts2拦截器的使用 (详解) 如何使用struts2拦截器,或者自定义拦截器.特别注意,在使用拦截器的时候,在Action里面必须最后一定要引用struts2自带的拦截器缺省堆栈default ...

  3. 【Java EE (Struts2 + Spring + Hibernate)开发】:Struts2(二)之【拦截器机制】

    [Java EE (Struts2 + Spring + Hibernate)开发]:Struts2(二)之[拦截器机制] 本文地址:http://blog.csdn.net/shanglianlm/ ...

  4. java 拦截指定jsp_详解Struts2中对未登录jsp页面实现拦截功能

    struts2中拦截器大家都很经常使用,但是拦截器只能拦截action不能拦截jsp页面.这个时候就有点尴尬了,按道理来说没登录的用户只能看login界面不能够通过输入url进行界面跳转,这显然是不合 ...

  5. Spring MVC学习(8)—HandlerInterceptor处理器拦截器机制全解

    基于最新Spring 5.x,详细介绍了Spring MVC的HandlerInterceptor处理器拦截器机制,以及它的一系列拦截方法. 本次我们来学习Sring MVC的HandlerInter ...

  6. Struts2拦截器实现异常处理机制

    http://bbs.itcast.cn/thread-10364-1-1.html Struts2拦截器实现异常处理机制   在j2ee项目中,系统内部难免会出现一些异常,如果把异常放任不管直接打印 ...

  7. 基于SSH2框架Struts2拦截器的登录验证实现 来自菠萝大象

    本文为菠萝大象原创,如要转载请注明出处. 通过之前的 Struts2.1.6+Spring2.5.6+Hibernate3.3.1全注解实例详解系列文章,我们已经成功将这三种框架整合到了一起, 这次大 ...

  8. struts2拦截器简介

    2019独角兽企业重金招聘Python工程师标准>>> 一.理解Struts2拦截器 1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦 ...

  9. struts2拦截器的实现原理及源码剖析

    拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理.同时,拦截器也可以让你将通用的 ...

最新文章

  1. 正则表达式匹配单个字符(.、[]、\d、\D、\s、\S、\w、\W)
  2. 第一个Swift程序Hello World
  3. else 策略模式去掉if_如何用卫语句、策略模式、状态模式重构if-else语句
  4. Txt格式配置表无法解析的问题——BOM
  5. bootstrap 模态框无法使用_模态窗 Modal Window - 产品中的??注意力设计
  6. python3函数写文件路径时,怎么写文件路径
  7. 使用sshpass借助scp自动输入密码传输一个文件夹下的全部内容
  8. 微信小程序微商城(二):电商首页轮播、分类导航和新品特卖实现
  9. 下载!《Linux 命令行大全》pdf
  10. Win7扫雷的H5完整复刻实现(三) / 鼠标左右键同时按下事件与收尾工作的实现
  11. Java8新特性-Lambda表达式
  12. 投影仪是计算机的基本配置吗,投影仪如何设置
  13. 虚拟化和禁用安全启动的设置
  14. 张亮:十万级并发任务调度框架 ElasticJob 的定位与设计理念
  15. html做战网首页,战网更新agent一半不动
  16. IDEA 开发工具安装教程及破解步骤(激活至2099年)
  17. hashcat破解WiFi显示No hashes loaded的解决方法
  18. 远程手机教学|简单实用,1键远程协助老人使用智能手机
  19. 用SendMessage/PostMessage发送WM_SIZE消息
  20. Kubernetes(k8s)基础之二:容器编排介绍及概念

热门文章

  1. EDM邮件营销内容策略技巧
  2. 使用PhotoShop制作一个简易的Logo
  3. 为什么C++能屹立这么久?细说C++ 可以开发的 7 件事 以及 C++ 的特点和学习的优点
  4. GitHub Actions构建镜像并部署服务
  5. php:输入值/表单提交参数过滤,防止sql注入或非法攻击的方法
  6. 如何利用python爬取网站数据
  7. 微信分享和禁止分享写法
  8. php的 include_once 什么意思,【后端开发】php关于include_once与include之间的区别详解...
  9. mysql 源码 sln_在windows下使用vs2013编译和调试mysql源代码
  10. mysql 复合索引和普通索引的区别