Spring MVC 完整生命周期和异常处理流程图

news2024/11/5 0:55:07

先要明白
在这里插入图片描述

// 1. 用户发来请求: localhost:8080/user/1

// 2. 处理器映射器(HandlerMapping)的工作
// 它会找到对应的Controller和方法
@GetMapping("/user/{id}")  
public User getUser(@PathVariable Long id) {
    return userService.getById(id);
}

// 3. 处理器适配器(HandlerAdapter)的工作
// - 把URL中的"1"转成Long类型的1 (类型转换)
// - 检查id是否为空、是否是正数 (数据验证)
// - 把转换好的参数传给controller方法 (参数解析)
客户端/浏览器 前端控制器 (DispatcherServlet) 处理器映射器 (HandlerMapping) 处理器适配器 (HandlerAdapter) 控制器 (Controller) 服务层 (Service) 异常通知器 (@RestControllerAdvice) 异常解析器 (HandlerExceptionResolver) 前端控制器初始化 1. initMultipartResolver() 初始化文件上传解析器 2. initLocaleResolver() 初始化地区解析器 3. initThemeResolver() 初始化主题解析器 4. initHandlerMappings() 初始化处理器映射器 5. initHandlerAdapters() 初始化处理器适配器 6. initHandlerExceptionResolvers() 初始化异常解析器 请求处理阶段 1. 发送HTTP请求 (例如:POST /serve/onSale/1) 2. getHandler() 查找处理器 根据URL匹配HandlerMapping 返回HandlerExecutionChain 返回处理器执行链 3. getHandlerAdapter() 获取处理器适配器 适配器负责: 1.参数解析 2.类型转换 3.数据验证 返回适配器 业务处理阶段 4. handle(request, response, handler) 调用控制器方法 调用服务层方法 返回处理结果 返回ModelAndView 返回ModelAndView 业务处理出现异常 可能抛出: 1. ForbiddenOperationException 2. CommonException 3. 其他异常 异常被@RestControllerAdvice捕获 委托给异常解析器处理 异常解析过程: 1. 判断异常类型 2. 选择处理策略 3. 转换为统一响应 处理FeignException 处理CommonException 处理普通Exception alt [Feign调用异常] [自定义业务异常] [其他异常] 返回处理结果 返回错误响应 alt [正常业务流程] [异常流程] 响应处理阶段 processDispatchResult() 处理ModelAndView 返回处理结果 处理错误视图 返回统一错误格式 alt [成功响应] [错误响应] 核心组件说明: 1. DispatcherServlet:Spring MVC的核心,统一的请求处理入口 2. HandlerMapping:负责URL与处理器的映射 3. HandlerAdapter:负责适配不同类型的处理器 4. Controller:处理具体的业务逻辑 5. @RestControllerAdvice:统一的异常处理切面 6. HandlerExceptionResolver:负责具体的异常处理策略 客户端/浏览器 前端控制器 (DispatcherServlet) 处理器映射器 (HandlerMapping) 处理器适配器 (HandlerAdapter) 控制器 (Controller) 服务层 (Service) 异常通知器 (@RestControllerAdvice) 异常解析器 (HandlerExceptionResolver)
重要说明
响应处理阶段
异常处理阶段
业务处理阶段
请求处理阶段
前端控制器初始化阶段
找到
未找到
支持
不支持
成功
失败
Feign异常
业务异常
其他异常
前端控制器
DispatcherServlet
处理器映射器
HandlerMapping
处理器适配器
HandlerAdapter
异常通知器
@RestControllerAdvice
异常解析器
HandlerExceptionResolver
构建响应对象
返回HTTP响应
检查异常类型
FeignException处理
CommonException处理
Exception处理
是否内部调用
内部异常处理
外部异常处理
设置异常头信息
构建错误响应
调用服务层方法
是否成功
返回处理结果
抛出异常
查找处理器
接收HTTP请求
获取处理器适配器
返回404
适配器是否支持
调用控制器方法
返回错误信息
初始化文件上传解析器
initMultipartResolver
前端控制器初始化
初始化地区解析器
initLocaleResolver
初始化主题解析器
initThemeResolver
初始化处理器映射器
initHandlerMappings
初始化处理器适配器
initHandlerAdapters
初始化异常解析器
initHandlerExceptionResolvers
开始
结束

我用生活中的例子解释 @RestControllerAdvice 的工作原理:
想象一个大型商场的客服中心:

  1. DispatcherServlet就像商场的总服务台
  • 负责接收所有顾客的需求并分配给相应的专柜处理
  1. @RestControllerAdvice就像商场的客服中心
  • 设立在商场的一个统一位置
  • 专门处理各个专柜出现的问题和投诉

举个具体场景:

顾客在商场购物的流程:

1. 正常流程:
顾客 -> 总服务台(DispatcherServlet) -> 专柜(Controller) -> 购买商品

2. 出现问题时:
专柜(Controller)出现问题 -> 客服中心(@RestControllerAdvice)接手处理 -> 给顾客一个合理解释

用代码表示:

// 这就像设立一个统一的客服中心
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    // 这就像专门处理"商品缺货"的客服人员
    @ExceptionHandler(ProductOutOfStockException.class)
    public ResponseEntity<String> handleOutOfStock(ProductOutOfStockException e) {
        // 返回友好提示:"非常抱歉,商品暂时缺货,预计3天后到货"
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                           .body("商品暂时缺货,预计3天后到货");
    }
    
    // 这就像处理"商品价格异常"的客服人员
    @ExceptionHandler(PriceException.class)
    public ResponseEntity<String> handlePriceError(PriceException e) {
        // 返回友好提示:"价格显示异常,请稍后重试"
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                           .body("价格显示异常,请稍后重试");
    }
}

为什么能拦截异常?
就像商场里:

  1. 所有专柜都在商场里面
  2. 客服中心在商场的入口处
  3. 一旦专柜出问题,就会按照商场规定,统一转到客服中心处理

在Spring中:

  1. DispatcherServlet(总服务台)知道有这个@RestControllerAdvice(客服中心)的存在
  2. 当Controller(专柜)抛出异常时
  3. DispatcherServlet就会把异常转给@RestControllerAdvice处理

关键点:

  • 它不是拦截,而是异常发生后的统一处理
  • Spring框架帮我们做了这个转发操作
  • 这样我们就不用在每个Controller里写重复的异常处理代码
客户端 DispatcherServlet Controller @RestControllerAdvice 异常通知类 @ExceptionHandler 异常处理方法 正常请求流程 1. 发送HTTP请求 2. 转发到Controller 异常发生和处理流程 3. 业务处理过程中抛出异常 @RestControllerAdvice的作用 1. 是@ControllerAdvice的特殊形式 2. 会自动扫描所有Controller 3. 集中处理所有异常 4. 异常被@RestControllerAdvice捕获 @ExceptionHandler的作用 1. 指定要处理的异常类型 2. 根据异常类型匹配处理方法 3. 将异常转换为友好响应 5. 根据异常类型找到对应的处理方法 处理微服务调用异常 处理业务异常 处理未知异常 alt [FeignExcept- ion异常] [CommonExc- eption异常] [其他Exceptio- n] 响应处理 6. 返回处理后的Result对象 7. 转换为HTTP响应返回 重要说明: 1. @RestControllerAdvice相当于异常的"统一接待处" 2. @ExceptionHandler相当于不同类型异常的"专门处理窗口" 3. 整个过程自动完成,使异常处理从业务代码中解耦 客户端 DispatcherServlet Controller @RestControllerAdvice 异常通知类 @ExceptionHandler 异常处理方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2230834.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

wps宏代码学习

推荐学习视频&#xff1a;https://space.bilibili.com/363834767/channel/collectiondetail?sid1139008&spm_id_from333.788.0.0 打开宏编辑器和JS代码调试 工具-》开发工具-》WPS宏编辑器 左边是工程区&#xff0c;当打开多个excel时会有多个&#xff0c;要注意不要把…

vscode | 开发神器vscode快捷键删除和恢复

目录 快捷键不好使了删除快捷键恢复删除的快捷键 在vscode使用的过程中&#xff0c;随着我们自身需求的不断变化&#xff0c;安装的插件将会持续增长&#xff0c;那么随之而来的就会带来一个问题&#xff1a;插件的快捷键重复。快捷键重复导致的问题就是快捷键不好使了&#xf…

Java-02

笔试算法&#xff1a; 41. 回文串 我们称一个字符串为回文串&#xff0c;当且仅当这个串从左往右和从右往左读是一样的。例如&#xff0c;aabbaa、a、abcba 是回文串&#xff0c;而 ab、ba、abc 不是回文串。注意单个字符也算是回文串。 现在&#xff0c;给你一个长度为n的…

《数字图像处理基础》学习05-数字图像的灰度直方图

目录 一&#xff0c;数字图像的数值描述 &#xff11;&#xff0c;二值图像 &#xff12;&#xff0c;灰度图像 3&#xff0c;彩色图像 二&#xff0c;数字图像的灰度直方图 一&#xff0c;数字图像的数值描述 在之前的学习中&#xff0c;我知道了图像都是二维信息&…

6.1、实验一:静态路由

源文件获取&#xff1a;6.1_实验一&#xff1a;静态路由.pkt: https://url02.ctfile.com/f/61945102-1420248902-c5a99e?p2707 (访问密码: 2707) 一、目的 理解路由表的概念 会使用基础命令 根据需求正确配置静态路由 二、准备实验 1.实验要求 让PC0、PC1、PC2三台电脑…

集成ruoyi-it管理系统,遇到代码Bug

前言&#xff1a;这次ruoyi框架开发it管理系统&#xff0c;出现很多问题&#xff0c;也有学到很多东西&#xff0c;出现几个问题&#xff0c;希望下次项目不会出现或者少出现问题&#xff1b;其中还是有很多基础知识有些忘记&#xff0c;得多多复习 1&#xff1a;当写的代码没…

解决Redis缓存穿透(缓存空对象、布隆过滤器)

文章目录 背景代码实现前置实体类常量类工具类结果返回类控制层 缓存空对象布隆过滤器结合两种方法 背景 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库 常见的解决方案有两种&#xff0c;分别…

基于微信小程序的校园失物招领系统的研究与实现(V4.0)

博主介绍&#xff1a;✌stormjun、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

vscode 创建 vue 项目时,配置文件为什么收缩到一起展示了?

一、前言 今天用 vue 官方脚手架创建工程&#xff0c;然后通过 vscode 打开项目发现&#xff0c;配置文件都被收缩在一起了。就像下面这样 这有点反直觉&#xff0c;他们应该是在同一层级下的&#xff0c;怎么会这样&#xff0c;有点好奇&#xff0c;但是打开资源管理查看&…

LInux系统编程(二)操作系统和进程

目录 一、前言&#xff1a;冯诺依曼体系结构 1、图中各个单元的介绍 2、值得注意的几点 二、操作系统 1、操作系统分层图 2、小总结 三、 进程&#xff08;重点&#xff09; 1、进程的基本概念 2、存放进程信息的数据结构——PCB&#xff08;Linux 下称作 task_struct…

HNU-小学期-专业综合设计

写在前面 选题&#xff1a;大数据技术-智慧交通预测系统 项目github地址&#xff08;如果有用麻烦点个star与follow&#xff09;&#xff1a;https://github.com/wolfvoid/HNU-ITPS &#xff08;全部代码以及如何部署参见README&#xff09; 项目报告&#xff1a;如下&…

Linux特种文件系统--tmpfs文件系统

tmpfs类似于RamDisk&#xff08;只能使用物理内存&#xff09;&#xff0c;使用虚拟内存&#xff08;简称VM&#xff09;子系统的页面存储文件。tmpfs完全依赖VM&#xff0c;遵循子系统的整体调度策略。说白了tmpfs跟普通进程差不多&#xff0c;使用的都是某种形式的虚拟内存&a…

PLC会被卡脖子吗?冗余技术才是中型和大型PLC的门槛

美方称北京天圣华参与高超音速武器的研发和空对空导弹的生产&#xff0c;因此把北京天圣华列入实体制裁清单。据说因为天圣华向和中国军方相关研究机构出售了西门子的建模软件&#xff0c;并为军工项目的也就做出了积极贡献&#xff0c;因此美方对西门子施压。 西门子是全球最大…

【测试平台】打包 jenkins配置和jenkinsfile文件

背景&#xff1a; 当打包机环境配置完成后&#xff0c;需要挂到master的jenkins中&#xff0c;完成调度。 jenkins启动 命令行直接启动即可。 nohup java -jar /usr/local/opt/jenkins/libexec/jenkins.war --httpListenAddress0.0.0.0 --httpPort80 appending output to n…

【刷题13】链表专题

目录 一、两数相加二、两两交换链表的节点三、重排链表四、合并k个升序链表五、k个一组翻转链表 一、两数相加 题目&#xff1a; 思路&#xff1a; 注意整数是逆序存储的&#xff0c;结果要按照题目的要求用链表连接起来遍历l1的cur1&#xff0c;遍历l2的cur2&#xff0c;和…

人工智能与数据安全:Facebook如何应对隐私挑战

在数字时代&#xff0c;数据隐私和安全成为了用户和企业关注的核心问题。作为全球最大的社交媒体平台之一&#xff0c;Facebook面临着日益严峻的隐私挑战。近年来&#xff0c;频繁发生的数据泄露事件和对用户隐私的质疑&#xff0c;使得Facebook在保护用户数据方面倍感压力。为…

凸极式发电机的相量图分析和计算,内功率因数角和外功率因数角和功角的定义。

图1&#xff1a;同步发电机稳态相量图 若发电机为凸极式&#xff0c;由于凸极机正、交轴同步电抗不等&#xff0c;即xd≠xq&#xff0c;因此必须先借助虚构电动势 E ˙ Q E ˙ q − ( x d − x q ) I ˙ d \dot{E}_Q\dot{E}_q-(x_d-x_q)\dot{I}_d E˙Q​E˙q​−(xd​−xq​)…

C语言模拟实现堆排序

堆排序是一种效率比较高的排序方法&#xff0c;时间复杂度。 堆分为大堆和小堆&#xff0c;如果想要拍升序我们需要建立大堆&#xff0c;而如果想要拍降序则需要建立小堆&#xff0c;在使用堆排序前需要先建立一个堆&#xff0c;如果不会建立可以看我前面写的C语言模拟实现堆的…

HCIA笔记整合

第一部分&#xff1a; OSI七层模型 应用层&#xff1a;人机交互 抽象语言--------编码 表示层&#xff1a;编码------二进制 会话层&#xff1a;提供会话号 传输层&#xff1a;TCP/UDP 分段&#xff08;收到MTU值的限制&#xff09; MTU&#xff1a;最大传输单元&#xff…

html简易流程图

效果图 使用htmlcssjs&#xff0c;无图片&#xff0c;没用Canvas demo: <!DOCTYPE html> <html> <head><link href"draw.css" rel"stylesheet" /><script src"draw.js" type"text/javascript"></…