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

Spring的异常处理机制详解

在Spring Boot MVC架构中,如果Service方法中的异常没有被捕获也没有被抛出,异常的处理流程如下:

1.默认异常处理流程

@RestControllerpublicclassUserController{@AutowiredprivateUserServiceuserService;@GetMapping("/user/{id}")publicUsergetUser(@PathVariableLongid){// 如果Service抛出异常且没有被捕获returnuserService.findById(id);// 异常会向上传播}}@ServicepublicclassUserService{publicUserfindById(Longid){// 这里发生异常(比如NullPointerException)// 但没有try-catch,也没有声明throwsreturnuserRepository.findById(id).orElseThrow(()->newRuntimeException("User not found"));}}

2.异常的传播路径

Service层异常 → Controller层 → DispatcherServlet → 框架处理

具体处理方式:

3.运行时异常(RuntimeException)

@ServicepublicclassUserService{publicvoidprocess(){// 运行时异常会自动向上传播intresult=10/0;// ArithmeticException}}

处理结果

  • 异常会传播到Controller
  • 如果没有@ExceptionHandler处理,会到DispatcherServlet
  • 最终返回HTTP 500状态码

4.受检异常(Checked Exception)

@ServicepublicclassUserService{publicvoidreadFile(){// 编译错误:必须处理或声明抛出// FileReader fr = new FileReader("file.txt");}publicvoidreadFile2()throwsIOException{// 必须声明throwsFileReaderfr=newFileReader("file.txt");}}

关键区别

  • 受检异常:编译时会报错,必须处理
  • 运行时异常:编译通过,运行时才暴露

5.Spring的异常处理机制

A. Controller级别的@ExceptionHandler

@RestControllerAdvicepublicclassGlobalExceptionHandler{@ExceptionHandler(RuntimeException.class)publicResponseEntity<String>handleRuntimeException(RuntimeExceptione){returnResponseEntity.status(500).body("Service Error: "+e.getMessage());}}

B. Service层使用声明式事务

@Service@TransactionalpublicclassUserService{publicvoidupdateUser(Useruser){// 事务方法中的异常会导致事务回滚userRepository.save(user);thrownewRuntimeException("Test rollback");}}

6.实际影响和最佳实践

不推荐的做法

@ServicepublicclassUserService{publicvoidriskyMethod(){// 异常被"吞掉",调用方不知道出错try{// 可能抛出异常的操作}catch(Exceptione){// 空的catch块,不记录也不抛出}}}

推荐的最佳实践

方案1:统一异常处理
@ServicepublicclassUserService{publicUserfindById(Longid){returnuserRepository.findById(id).orElseThrow(()->newUserNotFoundException("User not found with id: "+id));}}// 自定义业务异常publicclassUserNotFoundExceptionextendsRuntimeException{publicUserNotFoundException(Stringmessage){super(message);}}
方案2:使用AOP统一处理
@Aspect@ComponentpublicclassServiceExceptionAspect{@AfterThrowing(pointcut="execution(* com.example.service.*.*(..))",throwing="ex")publicvoidhandleServiceException(Exceptionex){// 记录日志、监控等log.error("Service层异常: ",ex);}}
方案3:响应式异常处理
@ServicepublicclassUserService{@TransactionalpublicUsercreateUser(UserDTOdto){try{// 业务逻辑returnuserRepository.save(user);}catch(DataIntegrityViolationExceptione){thrownewBusinessException("用户已存在",e);}catch(Exceptione){log.error("创建用户失败",e);thrownewSystemException("系统错误,请稍后重试",e);}}}

7.重要结论

  1. 运行时异常:会自动传播,最终返回HTTP 500
  2. 受检异常:编译时强制要求处理
  3. 默认响应:未处理的异常会生成包含错误详情的HTTP 500响应
  4. 事务影响:Spring事务管理会回滚运行时异常
  5. 日志记录:异常栈会记录在服务器日志中

建议:即使在Service层,也应该适当处理异常,至少记录日志,并根据业务需要转换为合适的业务异常再向上抛出。

http://www.jsqmd.com/news/145288/

相关文章:

  • 云徙科技:企业全链路AI解决方案赋能伙伴
  • 锐捷设备批量下发配置telnetlib模块
  • Java 异常捕获基础知识:Exception、Error 和 Throwable
  • 2025年技术人才外派公司全攻略:核心误区、能力对比与落地避坑指南
  • 《复利效应》精读笔记
  • 【毕业设计】基于springboot的居民小区物业管理系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • 【毕业季紧急预警:58% 重复率 + 48 小时交稿,我靠这个工具逆天改命!】
  • 【谁懂啊!科研狗的降重血泪史谁能破?】
  • AI 2.0提示工程架构师职业规划:3条发展路径与晋升策略
  • 【客户案例】某大型保险:CMDB纳管之后,如何管住存量盘活增量数据?
  • PINNs分数阶扩散方程的参数反演模型MATLAB代码
  • 计算机Java毕设实战-基于springboot+vue的某零售商经营平台的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 【微电网调度】梯级水光互补系统最大化可消纳电量期望短期优化调度模型附matlab实现
  • 【微电网调度】梯级水光互补系统最大化可消纳电量期望短期优化调度模型附matlab实现
  • 完整教程:FastAPI项目:搭建一个搜索系统,可选不同搜索引擎进行搜索
  • 东方博宜OJ 2557:幂次求和 ← 数位DP
  • 东方博宜OJ 2557:幂次求和 ← 数位DP
  • [idioms from fables] cry wolf, bell the cat, sour grapes
  • 基于GA-BP的电涡流传感器称重系统温度补偿附matlab代码
  • 构建大数据领域数据服务的生态系统
  • shift-register应用案例
  • Kafka Streams实战:轻量级大数据流处理框架
  • 【课程设计/毕业设计】基于springboot的居民小区物业管理系统的设计与实现“物业办公 - 业主服务 - 数据监管” 三位一体的数字化架构【附源码、数据库、万字文档】
  • spring-事务
  • 【课程设计/毕业设计】基于Springboot的特产销售平台设计与实现基于springboot的某零售商经营平台的设计与实现【附源码、数据库、万字文档】
  • 【毕业设计】基于微服务教材征订系统(源码+文档+远程调试,全bao定制等)
  • 基于GA-WNN的电涡流传感器温度补偿附Matlab代码
  • 华为批量下发配置命令使用telnetlib模块
  • 手足口病主要病原体:肠道病毒EV71结构与重组蛋白研究全解析
  • vivo X300 Pro:长焦封神但也有小遗憾