SpringBoot之统一异常处理

SpringBoot之统一异常处理

目录

统一异常处理

代码示例 

运行结果 

问题

结合源码了解问题源头 

优点


统一异常处理

统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,
@ControllerAdvice 表⽰控制器通知类, @ExceptionHandler 是异常处理器,两个结合表
⽰当出现异常的时候执⾏某个通知,也就是执⾏某个方法事件。
代码示例 

ExceptionAdvice 

接⼝返回为数据时, 需要加 @ResponseBody 注解!!!

import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import springbook.model.Result; @Slf4j @ResponseBody @ControllerAdvice public class ExceptionAdvice { @ExceptionHandler public Result handlerException(Exception e){ log.error("发生异常, e: {}", e); return Result.fail("内部错误"); } @ExceptionHandler public Result handlerException(NullPointerException e){ log.error("发生异常, e:", e); return Result.fail("发生空指针异常"); } @ExceptionHandler public Result handlerException(ArithmeticException e){ log.error("发生异常, e:", e); return Result.fail("发生算术异常"); } }

 Result

import lombok.Data; import springbook.enums.ResultStatus; @Data public class Result<T> { private ResultStatus code; private String errMsg; //错误信息, 如果业务成功, errMsg为空 private T data; public static <T> Result success(T data){ Result result = new Result<>(); result.setCode(ResultStatus.SUCCESS); result.setData(data); return result; } public static Result fail(String msg){ Result result = new Result<>(); result.setCode(ResultStatus.FAIl); result.setErrMsg(msg); return result; } public static Result fail(ResultStatus resultStatus, String msg){ Result result = new Result<>(); result.setCode(resultStatus); result.setErrMsg(msg); return result; } }

TestController

import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/test") @RestController public class TestController { @RequestMapping("/t1") public String t1(){ int result = 10/0; return "string"; } @RequestMapping("/t2") public Integer t2(){ String str = null; System.out.println(str.length()); return 1; } @RequestMapping("/t3") public Boolean t3(){ Integer[] integers = new Integer[]{1,2,3,4}; System.out.println(integers[5]); return true; } }
运行结果 

t1的运行结果:

t2的运行结果:

t3的运行结果:

问题

我们知道,ArithmeticException和NullPointerException都属于RuntimeException,同时RuntimeException又属于Exception。

那么为什么同时有处理ArithmeticException和Exception的方法时,针对ArithmeticException异常,会调用处理ArithmeticException异常的方法而不是调用处理Exception异常的方法?

那么为什么同时有处理NullPointerException和Exception的方法时,针对NullPointerException异常,会调用处理NullPointerException异常的方法而不是调用处理Exception异常的方法?

结合源码了解问题源头 

下面通过Debug的方式,结合源码来剖析为什么会出现上面的问题。

以上面代码的访问test/t1路径下方法导致ArithmeticException异常为例:

经过Debug,我了解到,处理异常会走到下图所示的ExceptionHandlerMethodResolver类里面的getMapperMethod()方法:

在刚进入该方法的时候,经过第一个黄色框内代码的处理后,会把当前具有处理异常的方法结合当前发生的异常进行匹配,最终匹配到两个合适类型的异常,分别是Exception异常和ArithmeticException异常:

但是在经过第二个黄色框内的代码处理后,会对刚刚匹配到的异常进行排序,根据异常的深度进行排序,并返回深度最浅的异常(即返回最合适的异常)。

经过第二个黄色框内的代码处理后,matches里面的内容顺序发生变动:

此时,我们就知道了为什么同时有处理ArithmeticException和Exception的方法时,针对ArithmeticException异常,会调用处理ArithmeticException异常的方法而不是调用处理Exception异常的方法;以及为什么同时有处理NullPointerException和Exception的方法时,针对NullPointerException异常,会调用处理NullPointerException异常的方法而不是调用处理Exception异常的方法。

优点
1. 提高用户体验
        友好的错误信息:通过统一异常处理,可以为前端或其他服务提供一致的、易于理解的错误信息,而不是直接暴露后端的堆栈跟踪或技术细节,从而提升用户体验。
        避免敏感信息泄露:统一处理可以避免在异常响应中不小心泄露敏感信息,如数据库表结构、内部实现细节等。
2. 业务逻辑和异常处理逻辑解耦
        代码结构清晰:将异常处理逻辑从业务逻辑中分离出来,使得业务代码更加专注于业务逻辑的实现,而异常处理代码则专注于异常的捕获、处理和响应。
        易于维护:当需要修改异常处理逻辑时,只需在统一异常处理类中修改,而无需在多个业务代码中逐一修改,降低了维护成本。
3. 减少冗余代码
        避免重复编写:在传统的Java开发中,异常处理通常是分散在代码的各个部分中的。而使用统一异常处理可以避免在每个可能抛出异常的地方编写重复的异常处理代码。
        提高代码复用性:通过定义全局的异常处理类,可以实现对多种异常的统一处理,提高代码的复用性。
4. 便于代码风格统一
        风格一致:统一异常处理有助于保持代码风格的一致性,使得整个项目的代码更加规范、整洁。
        提升可读性:对于其他开发者来说,阅读和理解统一异常处理的代码也更为容易。
5. 便于异常监控和日志记录
        集中监控:通过统一异常处理,可以更容易地实现对异常情况的集中监控和统计,为后续的故障排查和性能优化提供依据。
        详细日志:在异常处理过程中,可以记录详细的异常信息和上下文信息,便于后续的日志分析和问题定位。

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk