SpringMVC拦截器(Java学习笔记)

拦截器(Interceptor)是 Spring MVC 提供的一种强大的功能组件。它可以对用户请求进行拦截,并在请求进入控制器(Controller)之前、控制器处理完请求后、甚至是渲染视图后,执行一些指定的操作。

在 Spring MVC 中,拦截器的作用与 Servlet 中的过滤器类似,它主要用于拦截用户请求并做相应的处理,例如通过拦截器,我们可以执行权限验证、记录请求信息日志、判断用户是否已登录等操作。

Spring MVC 拦截器使用的是可插拔式的设计,如果我们需要某一拦截器,只需在配置文件中启用该拦截器即可;如果不需要这个拦截器,则只要在配置文件中取消应用该拦截器即可。

定义拦截器

想要在 Spring MVC 项目中使用拦截器,第一步就是要对拦截器类进行定义。

Spring MVC 在 org.springframework.web.servlet 包中提供了一个 HandlerInterceptor 接口,该接口包含 3 个方法,如下表。

方法名返回值说明
preHandle ()boolean该方法在控制器方法之前执行,其返回值用来表示是否中断后续操作。返回值为 true 时,表示继续向下执行;返回值为 false 时,表示中断后续的操作。
postHandle ()void该方法会在控制器方法调用之后,解析式图之前执行。我们可以通过此方法对请求域中的模型(Model)数据和视图做出进一步的修改。
afterCompletion ()void该方法会在整个请求完成后,即视图渲染结束之后执行。我们可以通过该方法实现资源清理、日志记录等工作。
package com.example.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle 执行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle 执行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion 执行");
    }
}

配置拦截器

在定义完拦截器后,我们还需要在 Spring MVC 的配置文件中使用 mvc:interceptors 标签及其子标签对拦截器进行配置,这样这个拦截器才会生效。

  1. 通过 子标签配置全局拦截器
    我们可以在 Spring MVC 的配置文件中,通过 mvc:interceptors 标签及其子标签 ,将我们自定义的拦截器配置成了一个全局拦截器。该拦截器会对项目内所有的请求进行拦截,配置代码如下。
<!--配置拦截器-->
<mvc:interceptors>
    <bean class="net.biancheng.c.interceptor.MyInterceptor"></bean>
</mvc:interceptors>
  1. 通过 子标签配置全局拦截器
    除了 标签外,我们还可以在 mvc:interceptors 标签中通过子标签 定义一个全局拦截器引用,对所有的请求进行拦截。
<!--将自定义的拦截器放到 ioc 容器中-->
<bean id="interceptor" class="net.biancheng.c.interceptor.MyInterceptor"></bean>
<!--配置拦截器-->
<mvc:interceptors>
    <!--通过 ref 配置全局拦截器-->
    <ref bean="interceptor"></ref>
</mvc:interceptors>

注意:mvc:interceptors 标签的 子标签不能单独使用,它需要与 标签(mvc:interceptors 标签内或mvc:interceptors标签外)或 @Component 等注解配合使用,以保证 标签配置的拦截器是Spring IOC 容器中的组件。
3. 通过mvc:interceptor子标签对拦截路径进行配置
我们还可以在 Spring MVC 的配置文件中通过 mvc:interceptors 标签的子标签 mvc:interceptor,对拦截器拦截的请求路径进行配置,示例配置如下。

<!--配置拦截器-->
<mvc:interceptors>
    <!--拦截器 1-->
    <mvc:interceptor>
        <!--配置拦截器拦截的请求路径-->
        <mvc:mapping path="/**"/>
        <!--配置拦截器不需要拦截的请求路径-->
        <mvc:exclude-mapping path="/login"/>
        <mvc:exclude-mapping path="/"/>
        <!--定义在 <mvc:interceptors> 下,表示拦截器只对指定路径的请求进行拦截-->
        <bean class="net.biancheng.c.interceptor.MyInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

需要注意的是,在 mvc:interceptor 中,子元素必须按照上述代码的配置顺序进行编写,即 mvc:mapping → mvc:exclude-mapping → 的顺序,否则就会报错。其次,以上这三种配置拦截器的方式,我们可以根据自身的需求以任意的组合方式进行配置,以实现在 mvc:interceptors 标签中定义多个拦截器的目的。

拦截器的执行流程

MyInterceptorpreHandle
retuen_true
HandlerAdapter#handle控制器方法处理请求
MyInterceptor#postHandle
DispatcherServlet#render对视图进行渲染
MyIntercepter#afterCompletion

拦截器处理流程的步骤如下:

  1. 当请求的路径与拦截器拦截的路径相匹配时,程序会先执行拦截器类(MyInterceptor)的 preHandl() 方法。若该方法返回值为 true,则继续向下执行 Controller(控制器)中的方法,否则将不再向下执行;
  2. 控制器方法对请求进行处理;
    3.调用拦截器的 postHandl() 方法,此时我们可以对请求域中的模型(Model)数据和视图做出进一步的修改;
  3. 通过 DispatcherServlet 的 render() 方法对视图进行渲染;
  4. 调用拦截器的 afterCompletion () 方法,完成资源清理、日志记录等工作。

多个拦截器的执行流程

在大型的企业级项目中,通常都不会只有一个拦截器,开发人员可能会定义许多不同的拦截器来实现不同的功能。在程序运行期间,拦截器的执行是有一定的顺序的,该顺序与拦截器在配置文件中定义的顺序有关。

假设一个项目中包含两个不同的拦截器:Interceptor1 和 Interceptor2,它们在配置文件中定义的顺序为:Interceptor1 → Interceptor2。下面我们就通过一个拦截器流程图来描述下多个拦截器的执行流程。
在这里插入图片描述
从上面的执行流程图可以看出,当存在多个拦截器同时工作时,它们的 preHandle() 方法会按照拦截器在配置文件中的配置顺序执行,但它们的 PostHandle() 和 afterCompletion() 方法则会按照配置顺序的反序执行。

如果其中有拦截器的 preHandle() 方法返回了 false,各拦截器方法执行情况如下。
第一个返回 preHandle() 方法 false 的拦截器以及它之前的拦截器的 preHandle() 方法都会执行。
所有拦截器的 postHandle() 都不会执行。
第一个返回 preHandle() 方法 false 的拦截器之前的拦截器的 afterComplation() 方法都会执行。

学习原文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值