Spring MVC拦截器

拦截器(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 该方法会在整个请求完成后,即视图渲染结束之后执行。我们可以通过该方法实现资源清理、日志记录等工作。

通过实现 HandlerInterceptor 接口,重写其方法,来实现对拦截器类的定义,示例代码如下。

java 复制代码
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> 标签及其子标签对拦截器进行配置,这样这个拦截器才会生效。

在 Spring MVC 的配置文件中,<mvc:interceptors> 标签用于定义一组拦截器,其包含多个常用的子标签,具体说明如下表。

标签 一级子标签 二级子标签 说明
<mvc:interceptors> <bean> - <mvc:interceptors> 标签的子标签,用于定义一个全局拦截器,对所有的请求进行拦截。
<mvc:interceptors> <ref> - <mvc:interceptors> 标签的子标签,用于定义一个全局拦截器的引用,对所有的请求进行拦截。 <mvc:interceptors> 标签的 <ref> 子标签不能单独使用,它需要与 <bean> 标签(<mvc:interceptors> 标签内或 <mvc:interceptors>标签外)或 @Component 等注解配合使用,以保证<ref> 标签配置的拦截器是 Spring IOC 容器中的一个组件。
<mvc:interceptors> <mvc:interceptor> <mvc:mapping> <mvc:interceptor> 标签用于定义一个指定拦截路径的拦截器。 <mvc:mapping> 标签则是<mvc:interceptor> 的子标签,用来配置拦截器拦截的路径,该路径则是通过其属性"path"中定义的。例如,path 的属性值为"/**"时,表示拦截所有请求;而"/hello"则表示拦截路径为"/hello"的请求。
<mvc:interceptors> <mvc:interceptor> <mvc:exclude-mapping> <mvc:exclude-mapping> 为<mvc:interceptor> 的子标签,用来配置不需要被拦截器拦截的路径。
<mvc:interceptors> <mvc:interceptor> <bean> <bean> 为<mvc:interceptor> 的子标签,用来定义一个指定了拦截路径的拦截器。
<mvc:interceptors> <mvc:interceptor>
<mvc:interceptors> <mvc:interceptor>

1. 通过 <bean> 子标签配置全局拦截器

在 Spring MVC 的配置文件中,通过 <mvc:interceptors> 标签及其子标签 <bean> ,将我们自定义的拦截器配置成了一个全局拦截器。该拦截器会对项目内所有的请求进行拦截,配置代码如下。

html 复制代码
<!--配置拦截器-->
<mvc:interceptors>
    <bean class="com.cky.interceptor.MyInterceptor"></bean>
</mvc:interceptors>

2. 通过 <ref> 子标签配置全局拦截器

除了 <bean> 标签外,还可以在 <mvc:interceptors> 标签中通过子标签 <ref> 定义一个全局拦截器引用,对所有的请求进行拦截。

html 复制代码
<!--将自定义的拦截器放到 ioc 容器中-->
<bean id="interceptor" class="com.cky.interceptor.MyInterceptor"></bean>
<!--配置拦截器-->
<mvc:interceptors>
    <!--通过 ref 配置全局拦截器-->
    <ref bean="interceptor"></ref>
</mvc:interceptors>

注意:<mvc:interceptors> 标签的 <ref> 子标签不能单独使用,它需要与 <bean> 标签(<mvc:interceptors> 标签内或<mvc:interceptors>标签外)或 @Component 等注解配合使用,以保证 <ref> 标签配置的拦截器是Spring IOC 容器中的组件。

3. 通过<mvc:interceptor>子标签对拦截路径进行配置

还可以在 Spring MVC 的配置文件中通过 <mvc:interceptors> 标签的子标签 <mvc:interceptor>,对拦截器拦截的请求路径进行配置,示例配置如下。

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

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

拦截器的执行流程

拦截器的执行流程如下图所示。

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

  1. 当请求的路径与拦截器拦截的路径相匹配时,程序会先执行拦截器类(MyInterceptor)的 preHandl() 方法。若该方法返回值为 true,则继续向下执行 Controller(控制器)中的方法,否则将不再向下执行;
  2. 控制器方法对请求进行处理;
  3. 调用拦截器的 postHandl() 方法,此时我们可以对请求域中的模型(Model)数据和视图做出进一步的修改;
  4. 通过 DispatcherServlet 的 render() 方法对视图进行渲染;
  5. 调用拦截器的 afterCompletion () 方法,完成资源清理、日志记录等工作。
相关推荐
考虑考虑3 小时前
Jpa使用union all
java·spring boot·后端
用户3721574261353 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊4 小时前
Java学习第22天 - 云原生与容器化
java
渣哥6 小时前
原来 Java 里线程安全集合有这么多种
java
间彧6 小时前
Spring Boot集成Spring Security完整指南
java
间彧6 小时前
Spring Secutiy基本原理及工作流程
java
Java水解7 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆9 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学10 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole10 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端