详解Struts2拦截器机制

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

  1. 拦截器在Struts中的作用
  2. 自定义拦截器实现类
  3. 配置拦截器(包含配置默认拦截器)
  4. 引用拦截器
  5. 配置拦截指定方法的拦截器
  6. 拦截器的拦截顺序

一、拦截器在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 MethodFilterInterceptor
 extends 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中拦截器器的相关知识,如需深刻理解还要在具体项目中体会,总结不到之处,望海涵!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 关于Struts2文件上传与自定义拦截器

    一.访问或添加request/session/application属性 public String scope() throws Exception{   ActionContext ctx = ActionContext.getContext();   ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app   ctx.getSession().put("ses", &q

  • java中的Struts2拦截器详解

    最近在学习struts的拦截器,现在来总结一下. 1.拦截器是什么? 拦截器相当于过滤器:就是将不想要的去掉,想要的留下.拦截器抽象出一部分代码可以用来完善原来的action.同时可以减轻代码冗余,提高重用率.通俗地讲就是一张网,过滤掉不需要的沙子,留下水. 2.拦截器的作用: 拦截器可以构成特定的功能.比如权限认证.日志记录和登陆判断. 3.拦截器的原理: 其每一个Action请求都在拦截器中,每一个action可以将操作转交给下面的拦截器,也可以直接退出到界面上. 4.定义拦截器: (1)自

  • struts2自定义拦截器的示例代码

    题目:使用struts2自定义拦截器,完成用户登陆才能访问权限的实现 在session中存放user变量表示用户登陆,若user为空则用户没有登陆,反之登陆 显示提示信息(请先登录) 定义拦截器 在struts.xml中定义拦截器使用标签<Intercaptors>.<Intercapter>. <interceptors> <interceptor name="test" class="Intercaptor.Intercaptor

  • Struts2拦截器登录验证实例

    Struts2拦截器 Struts2拦截器的概念和Spring Mvc拦截器一样. 1.Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 2.拦截器栈(Interceptor Stack).Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链.在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用. 使用拦截器的第一步: 自定义我的权限拦截器Chec

  • Java的Struts2框架中拦截器使用的实例教程

    1.拦截器小介 拦截器的功能类似于web.xml文件中的Filter,能对用户的请求进行拦截,通过拦截用户的请求来实现对页面的控制.拦截器是在Struts-core-2.2.3.jar中进行配置的,原始的拦截器是在struts-default.xml中配置的,里面封存了拦截器的基本使用方法. Struts2拦截器功能类似于Servlet过滤器.在Action执行execute方法前,Struts2会首先执行struts.xml中引用的拦截器,如果有多个拦截器则会按照上下顺序依次执行,在执行完所有

  • struts2过滤器和拦截器的区别分析

    本文分析了struts2过滤器和拦截器的区别.分享给大家供大家参考,具体如下: 一.本质区别: 1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调. 2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器. 3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用. 4. 拦截器可以访问action上下文.值栈里的对象,而过滤器不能访问. 5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次 二.使用区别:

  • struts2如何使用拦截器进行用户权限控制实例

    大多数网站会设置用户权限,如过滤非法用户,用户不登录时不能进行访问,或者设置访问的权限,如部分内容仅对VIP开放等等,这些权限的控制都可以用struts2中的拦截器来实现. 下面通过一个简单的Demo来模拟这种用户权限控制的实现流程,设定三种不同身份的用户,commen为普通用户,VIP为会员用户,还有一种admin为管理员. 先看一下Demo的整体结构: 首先搭建struts2框架的开发环境(前面博客中有介绍),环境搭建完之后又再看一看如何配置struts.xml: <?xml version

  • java Struts2 在拦截器里的跳转问题

    复制代码 代码如下: java.lang.IllegalStateException at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:405) at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:725) at org.apache.struts2.dispatcher.Dispatcher.servi

  • 详解Struts2拦截器机制

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

  • 详解struts2的token机制和cookie来防止表单重复提交

    详解struts2的token机制和cookie来防止表单重复提交 今天在做一个投票系统时要实现防止表单重复提交! 当时就想到了用struts2提供的token机制 struts2的token机制防止表单重复提交: 首先需要在提交的jsp页面(要使用token机制,必须使用struts2提供的标签库)加上 <s:token></s:token> 这段代码,然后在struts.xml里面需要进行如下配置: <action name="token" class

  • 详解Spring 拦截器流程及多个拦截器的执行顺序

    拦截器是 Spring MVC 中的组件,它可以在进入请求方法前做一些操作,也可以在请求方法后和渲染视图后做一些事情. 拦截器的定义 SpringMVC 的拦截器只需要实现 HandlerInterceptor 接口,并进行配置即可.HandlerInterceptor 接口的定义如下: public interface HandlerInterceptor { default boolean preHandle(HttpServletRequest request, HttpServletRe

  • 详解Mybatis拦截器安全加解密MySQL数据实战

    需求背景 公司为了通过一些金融安全指标(政策问题)和防止数据泄漏,需要对用户敏感数据进行加密,所以在公司项目中所有存储了用户信息的数据库都需要进行数据加密改造.包括Mysql.redis.mongodb.es.HBase等. 因为在项目中是使用springboot+mybatis方式连接数据库进行增删改查,并且项目是中途改造数据.所以为了不影响正常业务,打算这次改动尽量不侵入到业务代码,加上mybatis开放的各种拦截器接口,所以就以此进行改造数据. 本篇文章讲述如何在现有项目中尽量不侵入业务方

  • 一文详解Java拦截器与过滤器的使用

    目录 流程图 拦截器vs过滤器 SpringMVC技术架构图 项目Demo 依赖 Interceptor拦截器 Filter过滤器 1.多Filter不指定过滤顺序 2.多Filter指定过滤顺序 流程图 拦截器vs过滤器 拦截器是SpringMVC的技术 过滤器的Servlet的技术 先过过滤器,过滤器过完才到DispatcherServlet: 拦截器归属于SpringMVC,只可能拦SpringMVC的东西: 拦截器说白了就是为了增强,可以在请求前进行增强,也可以在请求后进行增强,但是不一

  • 详解SpringMVC拦截器配置及使用方法

    本文介绍了SpringMVC拦截器配置及使用方法,分享给大家,具体如下: 常见应用场景 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等. 2.权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面: 3.性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录): 4.通用行为:读取cookie得到用户信

  • 详解SpringMVC拦截器(资源和权限管理)

    本文主要介绍了SpringMVC拦截器,具体如下: 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet. DispatcherServlet是前置控制器,配置在web.xml文件中的.拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller来处理.  所以我们现在web.xml中加入以下配置: <!-- 初始化 Dispatcher

  • 详解springmvc拦截器拦截静态资源

    springmvc拦截器interceptors springmvc拦截器能够对请求的资源路径进行拦截,极大的简化了拦截器的书写.但是,千万千万要注意一点:静态资源的放行. 上代码: <mvc:resources mapping="/resources/**" location="/static/resources" /> <mvc:resources mapping="/static/css/**" location=&quo

  • 详解Java拦截器以及自定义注解的使用

    目录 1,设置预处理,设置不需要拦截的请求 2.UserTokenInterceptor ,securityInterceptor分别处理不同的请求拦截,执行不同的拦截逻辑. 3.关于注解的使用 总结 1,设置预处理,设置不需要拦截的请求 @Component public class MyWebConfig implements WebMvcConfigurer { private final UserTokenInterceptor userTokenInterceptor; private

  • Struts2拦截器Interceptor的原理与配置实例详解

    一.Struts2拦截器原理: Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的    拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器. 比如:应用要求用户登陆,且必须为指定用户名才可以查看系统中某个视图资源:否则,系统直接转入登陆页面.对于上面的需求,可以在每个Action的执行实际处理逻辑之前,先执行权限检查逻辑,但这种做法不利于代码复用.因为大部分Action里的权限检查代码都大同小异,故

随机推荐