Struts2入门第十讲——Struts2的拦截器
发布日期:2021-06-30 18:00:22 浏览次数:4 分类:技术文章

本文共 5439 字,大约阅读时间需要 18 分钟。

拦截器的概述

什么是拦截器?

拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作,所以拦截是AOP的一种实现策略。在WebWork的中文文档中是这样解释拦截器的:拦截器是动态拦截Action调用的对象。它提供了一种机制使开发者可以定义在一个Action执行的前后执行的代码,也可以在一个Action执行前就阻止其执行。同时也是提供了一种可以提取Action中可重用的部分的方式。

谈到拦截器,还有一个词大家应该知道,那就是拦截器链(Interceptor Chain,在Struts2中称为拦截器栈,Interceptor Stack)。拦截器链就是将拦截器按一定的顺序连接成一条链,在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。下面是我对于拦截器概念的理解。

拦截器和过滤器的区别

之前在Java Web阶段,我们就学习过过滤器,现在又在学拦截器,那它俩之间有什么区别呢?拦截器和过滤器的区别如下:

  • Filter:过滤器,过滤从客户端向服务器发送的请求。理论上,它可以过滤任意内容,如过滤jsp、过滤html、过滤图片(路径)、过滤Servlet等;
  • Interceptor:拦截器是可以拦截内容,但它拦截的是客户端对Action的访问。其实,它是更细粒度化的拦截,因为它可以拦截Action中的具体的方法。

拦截器的实现原理

大部分时候,拦截器方法都是通过代理的方式来调用的。Struts2的拦截器实现相对简单,当请求到达Struts2的ServletDispatcher时,Struts2会查找配置文件,并根据其配置实例化相对应的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。Struts2的拦截器是可插拔的,拦截器是AOP的一种实现。关于对拦截器的底层实现原理,我的理解是拦截器的底层实现原理主要有两部分:

  • AOP思想:即面向切面(方面)编程思想。在实际开发中,比如说有一个基本的功能,但我们想扩展其基本的功能,这时就可以使用AOP思想了,也就是说能不修改其源代码便能扩展功能,比如登录功能,参考下图:
    在这里插入图片描述
  • 责任链模式(设计模式中的一种):它可以这样理解,有一组操作,比如增加、修改、删除等,按顺序执行这三个操作,首先执行增加操作,增加执行之后做类似于放行的操作,放行之后再执行修改操作,修改执行之后,做类似于放行的操作,放行之后最后再执行删除操作。这有点类似于过滤链(一个请求,可以有多个过滤器进行过滤,每个过滤器只有做放行操作,才能到达下一个过滤器)。

拦截器的执行流程

我们知道在Struts2框架里面有很多的拦截器,在拦截器里面帮我们实现了一部分功能。但Struts2框架里面的很多的拦截器,并不是都会执行,每次只会执行一些默认的拦截器,那这些默认的拦截器是在哪儿呢?Strtus2框架里面默认拦截器的位置是在struts2-core-2.3.24.jar包下的struts-default.xml文件中,在该文件中,我们便可找到默认拦截器的配置。

在这里插入图片描述
问题来了,拦截器是在什么时候执行的呢?在Action对象创建之后,在Action里面的方法执行之前执行拦截器。如果你一定要弄清楚拦截器的执行流程才肯罢休,那么你可以从源码的角度去分析,这时可以参考我花大力写的这篇文章——。

拦截器入门

环境搭建

首先肯定是要搭建Struts2的开发环境的,已经都学到这里了,想必你也已经知道了该如何搭建了,所以这儿就不费笔墨了。

然后,在src目录下新建一个com.meimeixia.web.action包,并在该包下创建一个Action,例如ActionDemo01类。

package com.meimeixia.web.action;import com.opensymphony.xwork2.ActionSupport;public class ActionDemo01 extends ActionSupport {
@Override public String execute() throws Exception {
System.out.println("ActionDemo01已经执行了......"); return super.execute(); }}

接着,在struts.xml文件中配置好自己编写的ActionDemo01类,就像下面这样:

/demo01/demo01.jsp

紧接着,在WebContent目录下新建一个demo01目录,并在该目录下新建一个demo01.jsp页面,内容如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%>
Insert title here

demo01.jsp

<% System.out.println("demo01.jsp已经执行了......"); %>

最后,试着在浏览器地址栏中输入http://localhost:8080/struts2_demo04/actionDemo01.action这样的URL地址进行访问,如果看到了自己想看的结果并没有报错,那么说明我们写的程序是没有问题的。这些准备工作做好之后,接下来就要在咱的程序中加入自定义拦截器了。

自定义拦截器

在程序开发过程中,如果需要开发自己的拦截器类,就需要直接或间接的实现com.opensymphony.xwork2.interceptor.Interceptor接口。其定义的代码如下:

在这里插入图片描述
从该接口的定义可知,它提供了三个方法,下面我会分别对它们进行具体介绍。
在这里插入图片描述
如果需要自定义拦截器,只需要实现Interceptor接口的三个方法即可。然而在实际开发过程中,除了实现Interceptor接口可以自定义拦截器外,更常用的一种方式是继承抽象拦截器类AbstractIntercepter。该类实现了Interceptor接口,并且提供了init()方法和destroy()方法的空实现。使用时,可以直接继承该抽象类,而不用实现那些不必要的方法。抽象拦截器类AbstractInterceptor中定义的方法如下所示:
在这里插入图片描述
从上述代码中可以看出,AbstractInterceptor类已经实现了Interceptor接口的所有方法,一般情况下,只需继承AbstractInterceptor类,实现interceptor()方法就可以创建自定义拦截器了。只有当自定义的拦截器需要打开系统资源时,才需要覆盖AbstractInterceptor类的init()方法和destroy()方法。与实现Interceptor接口相比,继承AbstractInterceptor类的方法更为简单。
经过上面知识的洗礼,我们已经知道了如何来定义一个拦截器了。于是,在src目录下新建一个com.meimeixia.web.interceptor包,并在该包下创建如下两个自定义拦截器,我们到是要看看这两个自定义拦截器是如何被调用的。

  • 第一个自定义拦截器,即InterceptorDemo01类。

    package com.meimeixia.web.interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;/** * 自定义的拦截器一 * @author liayun * */public class InterceptorDemo01 extends AbstractInterceptor {
    @Override public String intercept(ActionInvocation invocation) throws Exception {
    System.out.println("InterceptorDemo01拦截器执行了......"); //如果有下一个拦截器,就会执行下一个拦截器;如果没有,就执行Action String obj = invocation.invoke(); System.out.println("InterceptorDemo01拦截器执行结束了......"); return obj; }}
  • 第二个自定义拦截器,即InterceptorDemo02类。

    package com.meimeixia.web.interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;/** * 自定义的拦截器二 * @author liayun * */public class InterceptorDemo02 extends AbstractInterceptor {
    @Override public String intercept(ActionInvocation invocation) throws Exception {
    System.out.println("InterceptorDemo02拦截器执行了......"); //如果有下一个拦截器,就会执行下一个拦截器;如果没有,就执行Action String obj = invocation.invoke(); System.out.println("InterceptorDemo02拦截器执行结束了......"); return obj; }}

拦截器的配置

要想让拦截器起作用,首先要对它进行配置。拦截器的配置有两种方式,一种是定义拦截器的方式进行配置,一种是定义拦截器栈的方式进行配置。

定义拦截器的方式进行配置

拦截器的配置是在struts.xml文件中完成的,它通常以<interceptor>标签开头,以</interceptor>标签结束。定义拦截器的语法格式如下:

在这里插入图片描述
上述语法格式中,name属性用来指定拦截器的名称,class属性用来指定拦截器的实现类。有时,在定义拦截器时需要传入参数,这时需要使用<param>标签,其中name属性用来指定参数的名称,paramValue表示参数的值。
知道了如何配置一个拦截器之后,我们可以试着将上面两个自定义拦截器也配置一下,此时,struts.xml文件的内容就要修改为下面这个样子。
在这里插入图片描述
然后,在浏览器地址栏中输入http://localhost:8080/struts2_demo04/actionDemo01.action这样的URL地址进行访问,这时你就可以看到在Eclipse控制台中输出了如下内容。
在这里插入图片描述

定义拦截器栈的方式进行配置

在实际开发中,经常需要在Action执行前同时执行多个拦截动作,如:用户登录检查、登录日志记录以及权限检查等,这时,可以把多个拦截器组成一个拦截器栈。在使用时,可以将栈内的多个拦截器当成一个整体来引用。当拦截器栈被附加到一个Action上时,在执行Action之前必须先执行拦截器栈中的每一个拦截器。定义拦截器栈需要使用到<interceptors>元素和<interceptor-stack>子元素,当配置多个拦截器时,需要使用<interceptor-ref>元素来指定多个拦截器,配置语法如下:

...

在上述语法中,interceptorStackName值表示配置的拦截器栈的名称,interceptorName值表示拦截器的名称。除此之外,在一个拦截器栈中还可以包含另一个拦截器栈,示例代码如下:

在这里插入图片描述
在上述代码中,定义的拦截器栈是myStack,在myStack栈中,除了引用了两个自定义的拦截器interceptorDemo01和interceptorDemo02外,还引用了一个内置拦截器栈defaultStack,这个拦截器是必须要引入的。
好了,知道了如何配置一个拦截器栈之后,我们同样可以试着将上面两个自定义拦截器也配置一下,此时,struts.xml文件的内容就要修改为下面这个样子了。
在这里插入图片描述
这个时候,你在浏览器地址栏中输入http://localhost:8080/struts2_demo04/actionDemo01.action这样的URL地址进行访问,同样也可以看到在Eclipse控制台中输出了如下内容。
在这里插入图片描述
至此,Struts2中的拦截器总算是介绍完了。最后,感谢阅读,希望读者能够看懂,有所疑问可以留言。

转载地址:https://liayun.blog.csdn.net/article/details/68648101 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Spring入门第一讲——Spring框架的快速入门
下一篇:Struts2入门第十三讲——Struts2的标签库

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月27日 16时38分16秒