Spring MVC 多个拦截器的执行顺序

一、流程总览

该流程图描述了一个多层拦截器链的业务处理流程,核心逻辑为:

  1. 前置拦截 :通过 predHandler1predHandler2 逐层校验请求合法性。
  2. 核心处理 :通过校验后执行核心业务逻辑 handler()
  3. 后置处理与清理:按反向顺序执行后置操作,最终完成资源释放。

二、模块功能与业务场景
1. 前置拦截模块
  • predHandler1()
    • 业务作用:执行第一层基础校验(如用户身份验证、请求合法性检查)。
    • 逻辑分支
      • **返回 **false:请求非法或校验失败,直接终止流程(如用户未登录时返回401错误)。
      • **返回 **true:进入下一层校验 predHandler2()
  • predHandler2()
    • 业务作用:执行第二层精细化校验(如权限校验、参数合规性验证)。
    • 逻辑分支
      • **返回 **false:校验失败,仅触发 afterCompletion1()(如记录失败日志),流程终止。
      • **返回 **true:进入核心业务处理 handler()

2. 核心业务模块
  • handler()
    • 业务作用:执行实际业务逻辑(如数据计算、数据库操作、服务调用)。
    • 触发条件 :所有前置拦截器均通过(predHandler1predHandler2 均返回 true)。

3. 后置处理模块
  • postHandler2()
    • 业务作用:内层后置操作(如修改响应数据、记录操作日志)。
    • 执行顺序 :优先于外层后置操作(postHandler1()),确保依赖资源可用。
  • postHandler1()
    • 业务作用:外层后置操作(如统计请求耗时、格式化最终响应)。

4. 完成清理模块
  • afterCompletion1()
    • 业务作用:外层资源释放(如关闭数据库连接、清理临时文件)。
    • 触发条件 :只要 predHandler1 返回 true,无论后续流程是否成功,均会执行。
  • afterCompletion2()
    • 业务作用:内层资源释放(如提交事务、关闭内层连接)。
    • 触发条件predHandler2 返回 true 且流程执行到 handler() 后。

三、流程分支详解
分支 1: predHandler1** 返回 **false
  • 路径predHandler1 → 直接响应
  • 业务意义:基础校验失败,无需后续处理(如用户未登录时直接拒绝请求)。
分支 2: predHandler2** 返回 **false
  • 路径predHandler1 → predHandler2 → afterCompletion1
  • 业务意义:精细化校验失败(如用户无权限),但需释放外层资源(如记录失败日志)。
分支 3:所有拦截通过
  • 路径predHandler1 → predHandler2 → handler → postHandler2 → postHandler1 → afterCompletion2
  • 业务意义:完整处理请求,按反向顺序释放资源(如先提交事务,再关闭连接)。

四、流程设计的关键逻辑
  1. 前置顺序正向,后置顺序反向
    • 前置链 :由外到内逐层校验(predHandler1 → predHandler2),确保基础条件优先验证。
    • 后置链 :由内到外反向执行(postHandler2 → postHandler1),避免依赖资源提前释放。
  2. 资源释放的精准性
    • 外层资源 (如数据库连接)在 afterCompletion1 释放。
    • 内层资源 (如事务)在 afterCompletion2 释放,确保提交事务后再关闭连接。

五、实际应用场景
  1. API 请求校验链
    • predHandler1:验证 Token 有效性 → predHandler2:校验用户角色权限 → handler:返回数据。
    • 若角色权限不足,记录日志(afterCompletion1)并终止流程。
  2. 事务管理流程
    • predHandler1:打开数据库连接 → predHandler2:开启事务 → handler:执行业务 SQL。
    • postHandler2:提交事务 → postHandler1:关闭连接。
相关推荐
ldj202023 分钟前
CentOS上部署Redis及其哨兵(Sentinel)模式
数据库·redis·缓存
bing_1582 小时前
如何利用 Redis 的原子操作(INCR, DECR)实现分布式计数器?
数据库·redis·分布式
一个人的博客@你2 小时前
C#多数据库批量执行脚本工具
数据库·c#·批量执行·sql脚本·多数据库执行
果冻kk2 小时前
MySQL MVCC:并发神器背后的原理解析
数据库·mysql
卍郝凝卍3 小时前
云上服务器常见的存储方式和类型
大数据·服务器·数据库
axban3 小时前
QT中删除控件的注意事项、deleteLater和delete的区别
java·数据库·qt
喜欢敲代码的程序员4 小时前
SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:日志管理(四)集成Spring Security
spring boot·mysql·spring·vue·mybatis
Resean02234 小时前
SpringMVC 6+源码分析(二)DispatcherServlet实例化流程 1
java·spring boot·spring·servlet·springmvc
♪张三儿℡4 小时前
Oracle优化学习十六
数据库·学习·oracle
胡琦博客4 小时前
LLM Prompt与开源模型资源(3)如何写一个好的 Prompt
数据库·开源·prompt