当前位置: 首页 > news >正文

Spring MVC 拦截器interceptor

Spring MVC 过滤器interceptor

  • 拦截器
    • 定义
    • 概念与工作原理
    • **执行顺序**
      • 多拦截器执行顺序
    • 优势
  • 拦截器实现代码
    • xml 配置方式
      • 1. 实现HandlerInterceptor接口
      • 2. 配置XML文件,声明拦截路径
      • 3. 访问路径,触发拦截器
    • 配置类方式
      • 1. 实现HandlerInterceptor接口。
      • 2. 配置类实现webMvcConfigurer接口重载addInterceptors方法。
      • 3. 测试拦截器效果。
  • 拦截器 vs. 过滤器

示例代码地址:https://gitee.com/hua5h6m/framework-java/tree/master/spring-mvc-interceptor

拦截器三个方法拦截位置

拦截器

定义

Spring 拦截器 是 Spring MVC 框架提供的一种强大机制,它允许您在 HTTP 请求进入控制器控制器处理完请求后以及最终返回给用户前,注入自定义的预处理和后处理逻辑。

概念与工作原理

拦截器的工作流程基于 AOP 的设计思想,它围绕着 控制器方法的执行 进行拦截。

一个完整的拦截器生命周期包含三个关键时机点:

  1. preHandle - 预处理决定是否拦截,返回值为Boolean类型

    • 时机:在请求被 DispatcherServlet 接收后,但在调用目标 Controller(Handler)方法 之前 执行。
    • 作用:这是最常用、最重要的方法。常用于:
      • 权限验证:检查用户是否登录,是否有权限访问该接口。
      • 日志记录:记录请求信息,如 URL、IP、参数等。
      • 性能监控:记录请求开始时间。
      • 参数预处理:对请求参数进行统一的格式化或校验。
    • 返回值boolean 类型。
      • true:继续执行流程,调用下一个拦截器或最终的 Controller 方法。
      • false:中断请求,不再继续向下执行。通常在此方法中直接通过 response 返回结果。
  2. postHandle - 后处理

    • 时机:在 Controller 方法执行 之后,但在视图渲染或返回 JSON 之前 执行。
    • 作用
      • 对 Controller 返回的 ModelAndView 对象进行修改(例如,向模型中添加一些全局数据)。
      • 在返回视图前进行一些处理。
    • 注意:如果 Controller 方法内部发生了异常,此方法将 不会 被调用。
  3. afterCompletion - 请求完成回调

    • 时机:在整个请求完成 之后,即视图渲染完毕或响应已返回给客户端 之后 执行。
    • 作用
      • 资源清理:如清理 preHandle 中创建的线程局部变量。
      • 性能监控收尾:计算整个请求的耗时(需要与 preHandle 中记录的开始时间配合)。
      • 记录最终日志
    • 注意:无论 Controller 方法执行是否成功,此方法 总会被调用(类似于 try-catch-finally 中的 finally 块)。

执行顺序

Filter.doFilter() -> DispatcherServlet -> Interceptor.preHandle() -> Controller -> Interceptor.postHandle() -> 渲染视图 -> Interceptor.afterCompletion()


多拦截器执行顺序

在Spring MVC中,当存在多个拦截器时,它们的执行顺序由配置的先后顺序决定。具体来说,在配置类中通过InterceptorRegistry添加拦截器的顺序就是拦截器的执行顺序。或者在XML中,谁先配置谁先执行。

假设我们有两个拦截器:InterceptorAInterceptorB,并且我们先添加InterceptorA,再添加InterceptorB

  • 正常情况下的执行顺序(所有拦截器的preHandle都返回true):
  1. InterceptorA.preHandle()
  2. InterceptorB.preHandle()
  3. 执行控制器方法(Handler)
  4. InterceptorB.postHandle()
  5. InterceptorA.postHandle()
  6. InterceptorB.afterCompletion()
  7. InterceptorA.afterCompletion()

注意:preHandle方法是按照配置顺序执行的,而postHandleafterCompletion则是按照配置顺序的反向顺序执行。先进后出原则

优势

  • 核心概念:Spring 拦截器是 Spring MVC 中用于在控制器方法执行前后插入逻辑的组件。
  • 生命周期:包含 preHandle(最常用)、postHandleafterCompletion 三个关键方法。
  • 主要应用权限校验、日志记录、性能监控、通用参数处理 等横切关注点。
  • 核心优势:将通用的、非业务性的代码从业务控制器中解耦出来,使代码更加清晰、可维护和可复用。

拦截器实现代码

xml 配置方式

1. 实现HandlerInterceptor接口

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;public class UserInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle:handler触发之前");return true;}@Overridepublic void postHandle(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle:handler触发之后");}@Overridepublic void afterCompletion(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion:");}
}

2. 配置XML文件,声明拦截路径

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--配置注解扫码路径--><context:component-scan base-package="com.maven" /><!--配置控制器映射器和控制器适配器--><mvc:annotation-driven /><!--配置静态资源解析--><mvc:default-servlet-handler /><!--配置拦截器--><mvc:interceptors><!--第一个拦截器--><mvc:interceptor><!--拦截那些路径:默认全部拦截--><mvc:mapping path="/user/**"/><!--配置不拦截的路径--><mvc:exclude-mapping path="/user/list"/><!--指定拦截器的位置--><bean class="com.maven.interceptor.UserInterceptor" /></mvc:interceptor></mvc:interceptors>
</beans>

3. 访问路径,触发拦截器

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("user")
public class UserController {@GetMapping("info")public String info() {return "user info";}@GetMapping("list")public String list() {return "user list";}@GetMapping("exception")public String exception() {int i = 1 / 0;return "user exception";}
}
  • 访问/user/info,链接返回结果:
preHandle
postHandle
afterCompletion
  • 访问/user/exception,链接返回结果:
  • 页面报错500,因此postHandler不会触发,但是afterCompletion无论是否出现异常,都会执行。
preHandle
afterCompletion

配置类方式

1. 实现HandlerInterceptor接口。

  • 通过@Component注解,添加到容器中。
@Component
public class UserInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle");return HandlerInterceptor.super.preHandle(request, response, handler);}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion");}
}

2. 配置类实现webMvcConfigurer接口重载addInterceptors方法。

  • 一定不能忘记添加@Configuration注解。
  • 实现接口WebMvcConfigurer 接口,并重载addInterceptors方法。
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {@Autowiredprivate UserInterceptor userInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(userInterceptor).addPathPatterns("/user/**");}
}

3. 测试拦截器效果。

@RestController
@RequestMapping("user")
public class UserController {@GetMapping("info")public String info(){return "user info"+ new Date();}
}
  • 结果输出:
preHandle
postHandle
afterCompletion

拦截器 vs. 过滤器

这是一个非常常见的面试题,理解它们的区别至关重要。

特性Spring 拦截器Servlet 过滤器
出身Spring 框架 特有的组件。Servlet 规范 的一部分,任何 Java Web 应用都能用。
依赖依赖于 Spring 容器。不依赖于 Spring,只依赖于 Servlet 容器(如 Tomcat)。
作用域只能拦截 Spring MVC 的请求(即 DispatcherServlet 处理的请求)。可以拦截 所有 进入容器的请求(包括静态资源、JSP等)。
获取Bean可以轻松获取和注入 Spring 容器中的其他 Bean(如 Service)。默认不能,需要通过 SpringBeanAutowiringSupport 等特殊方式。
控制粒度可以获取到具体的 Handler(控制器方法) 信息。只能获取到 ServletRequest 和 ServletResponse。
执行时机DispatcherServlet 内部,Controller 方法执行的前后。DispatcherServlet 之前。
http://www.dtcms.com/a/511202.html

相关文章:

  • 如何在 CentOS、Ubuntu 和 Debian 云服务器上安装 Python 3
  • 《金融电子化》:构建金融韧性运行安全体系:从灾备管理到主动防御新范式​​
  • spark组件-spark core(批处理)
  • 进行网站建设视频教程装修网站cms
  • 解决Kali虚拟机中VMnet1(仅主机模式)网卡无法获取IP地址的问题
  • Linux驱动开发笔记(十一)——阻塞和非阻塞IO
  • Docker----快速入门
  • 深度学习8-卷积神经网络-CNN概述-卷积层-池化层-深度卷积神经网络-案例:服装分类
  • 厦门做外贸网站国内十大咨询公司排名
  • 架构设计过去十年与未来十年
  • Nginx 日志轮转
  • 《Linux运维总结:基于ARM64+X86_64架构CPU使用docker-compose一键离线部署mongodb 7.0.22容器版副本集群》
  • 《Linux运维总结:基于ARM64+X86_64架构CPU使用docker-compose一键离线部署mongodb 7.0.22容器版分片集群》
  • MongoDB基础与Mongoose ODM
  • 做定制网站价格教做flash的网站
  • 【流量控制】算不对 GBN 窗口?分不清 SR 重传?滑动窗口 + 3 大协议一篇吃透
  • 临时插入的紧急任务如何影响整体进度
  • 国内net开发的网站建设网站建设费如何会计处理
  • Melos 使用指南:Flutter / Dart 多包管理工具!
  • React组件完全指南
  • TypeScript:npm的types、typings、@type的区别
  • 我的第一份开源贡献:小米工程师程赛的社区之旅
  • Python 基础 | 第八课:函数详解与应用
  • 火狐浏览器替换js脚本
  • 车载诊断架构 --- 由一个售后问题引发对P4时间的思考
  • 第3章 SQL数据定义语句
  • phpcms 网站m8 wordpress主题
  • Docker到Kubernetes的平滑迁移(服务网格实战)
  • 数据挖掘知识体系分析
  • 简述网站建设的五类成员做电商网站公司