SpringMVC 拦截器 Interceptor介绍

2022-01-06 0 By admin

SpringMVC的处理器拦截器类似于 Servlet 开发中的过滤器Filter,用于对处理器进行预先处理和后处理。
我们可以自己定义一些拦截器来实现一些特定的功能。
如果拦截器比较多,形成拦截器链条,简称拦截链,拦截链就是将拦截器按一定顺序形成一条,在被访问的时候,拦截器会一一被调用。

一、拦截器 Interceptor 概述

1.1、Interceptor拦截器和Filter过滤器比较

功能模块提供方不同:

  • 过滤器是servlet规范中的一部分,任何java Web工程都可以使用。
  • 拦截器是SpringMVC框架自己的,只有使用 SpringMVC框架的工程才能使用。

管理的对象不同:

  1. 过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截。
  2. 拦截器它是只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js是不会进行拦截的。

其他:
拦截器不存在初始化,可以连续被调用;过滤器只能初始化一次。

SpringMVC 框架Filter、Interceptor 执行顺序
SpringMVC 框架Filter、Interceptor 执行顺序

二、拦截器 Interceptor 开发示例

在 SpringMVC 框架中编写自己的拦截器,其步骤总体分为:

  1. 编写拦截器的实现类,实现 HandlerInterceptor接口中三个抽象方法。
  2. 在 SpringMVC 的配置文件中进行配置拦截器。

2.1、编写拦截器实现类

在 SpringMVC 框架中,要实现拦截器的功能,主要通过两种途径:

  1. 实现 HandlerInterceptor接口
  2. 继承 HandlerInterceptorAdapter抽象类

这里推荐使用实现 HandlerInterceptor接口方式,需要重写接口中的三个抽象方法。

public class Myinterceptor implements HandlerInterceptor {
  public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
      System.out.println("preHandle run!");
      return true;
  }
  
  public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
      System.out.println("postHandle run!");
  }
  public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
      System.out.println("afterCompletion run!");
  }
}

2.2、在配置文件中进行配置拦截器

在 SpringMVC 的配置文件中配置拦截器这里列举三种方法:

1、通过Bean 指令配置

指明拦截器的类位置,Spring 框架会创建为Bean,设置为拦截器。

<bean class="com.atguigu.interceptor.FirstInterceptor"></bean>

2、通过 Ref 指令配置
配置引用的拦截器的Bean Id,需要在拦截器类上添加 @Component 注解,让框架创建Bean。

<ref bean="firstInterceptor"></ref>

以上两种配置方式都是对 DispatcherServlet 所处理的所有的请求进行拦截;不能自定义灵活配置。

3、自定义灵活配置方法

  1. 通过ref或bean标签设置拦截器
  2. 通过mvc:mapping设置需要拦截的请求
  3. 通过mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求
<mvc:interceptor>
    <mvc:mapping path="/**"/>
    <mvc:exclude-mapping path="/testRequestEntity"/>
    <ref bean="firstInterceptor"></ref>
</mvc:interceptor>

三、HandlerInterceptor 接口介绍

在HandlerInterceptor 接口中,定义了 3 个方法,分别为preHandle()、postHandle()和afterCompletion()。

3.1、preHandle 方法

preHandle(…)方法在请求处理之前进行调用。
Spring MVC 中的Interceptor是链式调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor。每个Interceptor的调用会依据它的声明顺序依次执行。

一个Interceptor中最先执行的是preHandle方法:

  1. 可以在这个方法中进行一些前置初始化操作
  2. 或者是对当前请求做一个预处理,
  3. 也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。

该方法的返回值是布尔(Boolean)类型的:

  1. 当它返回为false时,表示请求结束,后续的Interceptor和控制器(Controller)都不会再执行。
  2. 当返回值为true时,就会继续调用下一个Interceptor的preHandle方法,如果已经是最后一个Interceptor的时候,就会是调用当前请求的控制器中的方法。

3.2、postHandle 方法

通过preHandle方法的解释,我们知道这个方法包括后面要说到的afterCompletion方法都只能在当前所属的 Interceptor的preHandle方法的返回值为true的时候,才能被调用。

  1. postHandle方法在当前请求进行处理之后,也就是在控制器中的方法调用之后执行,但是它会在 DispatcherServlet 进行视图返回渲染之前被调用。
  2. 所以我们可以在这个方法中对控制器处理之后的 ModelAndView 对象进行操作。
  3. postHandle 方法被调用的方向跟 preHandle 是相反的,也就是说,先声明的 Interceptor的 postHandle方法反而会后执行。

3.3、afterCompletion 方法

afterCompletion(…)方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。
因此,该方法将在整个请求结束之后,也就是在 DispatcherServlet渲染了对应的视图之后执行。
这个方法的主要作用是用于进行资源清理的工作。

四、多个拦截器的执行顺序

4.1、若每个拦截器的preHandle()都返回true

此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关。
preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行。

4.2、若某个拦截器的preHandle()返回了false

preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterComplation()会执行。

SpringMVC 中多个Interceptor 执行顺序
SpringMVC 中多个Interceptor 执行顺序