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

SpringMVC通过注解实现全局异常处理

一、为什么需要全局异常处理?

开发应用程序的过程中会遇到各种各样的异常,如数据库连接异常,网络请求异常和业务逻辑异常等。传统的try-catch模式在各个controller中处理由于太过于分散,代码冗余度过高,导致维护成本过高。

全局处理能够高效地解决这一问题

二、Spring全局异常的处理方式

SpringMVC通过@ControllerAdvice和@ExceptionHandler注解来实现全局异常处理

实现步骤:

1 创建自定义异常类
2 创建全局异常处理器,使用@ControllerAdvice注解
3 在处理器类中定义异常处理方法,使用@ExceptionHandler注解指定处理的异常类型
4 在异常处理方法中定义异常响应的格式和内容

三、具体实现

1 创建自定义异常类(以用户未找到为例)

// 用户未找到异常
public class UserNotFoundException extends RuntimeException {public UserNotFoundException() {super();}public UserNotFoundException(String message) {super(message);}
}// 数据验证异常
public class ValidationException extends RuntimeException {public ValidationException(String message) {super(message);}
}

2 创建全局异常处理器

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;// 全局异常处理器,会拦截所有控制器抛出的异常
@ControllerAdvice
public class GlobalExceptionHandler {// 处理用户未找到异常@ExceptionHandler(UserNotFoundException.class)@ResponseBody  // 将返回结果转换为JSON@ResponseStatus(HttpStatus.NOT_FOUND)  // 设置HTTP状态码为404public Result<Void> handleUserNotFoundException(UserNotFoundException e) {return Result.error(404, e.getMessage());}// 处理数据验证异常@ExceptionHandler(ValidationException.class)@ResponseBody@ResponseStatus(HttpStatus.BAD_REQUEST)  // 设置HTTP状态码为400public Result<Void> handleValidationException(ValidationException e) {return Result.error(400, e.getMessage());}// 处理其他未捕获的异常@ExceptionHandler(Exception.class)@ResponseBody@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)  // 设置HTTP状态码为500public Result<Void> handleOtherExceptions(Exception e) {// 实际项目中可以在这里记录日志return Result.error(500, "服务器内部错误:" + e.getMessage());}
}

3 在控制器中使用

@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public Result<User> getUser(@PathVariable Long id) {// 这里不再需要try-catch,异常会被全局异常处理器捕获User user = userService.getUserById(id);if (user == null) {throw new UserNotFoundException("用户不存在,ID: " + id);}return Result.success(user);}@PostMappingpublic Result<User> createUser(@RequestBody User user) {if (user.getName() == null || user.getName().isEmpty()) {throw new ValidationException("用户名不能为空");}User savedUser = userService.saveUser(user);return Result.success(savedUser);}
}

四、工作原理

  1. 当控制器方法中抛出异常时,Spring 会查找是否有匹配的@ExceptionHandler
  2. @ControllerAdvice注解的类会被 Spring 扫描到,并作为全局异常处理器
  3. Spring 会根据抛出的异常类型,找到对应的@ExceptionHandler方法
  4. 执行异常处理方法,返回统一的响应结果

五、高级用法

  1. 异常处理的优先级

    • 控制器内部的@ExceptionHandler优先于全局异常处理器
    • 子类异常的处理器优先于父类异常的处理器
  2. 结合日志记录

    @ExceptionHandler(Exception.class)
    public Result<Void> handleOtherExceptions(Exception e) {log.error("发生未捕获异常", e);  // 记录异常日志return Result.error(500, "服务器内部错误");
    }

六、总结

全局异常处理是 SpringMVC框架中一个非常实用的功能,通过@ControllerAdvice@ExceptionHandler注解可以轻松实现:

  1. 减少重复代码,提高开发效率
  2. 统一异常响应格式,便于前端处理
  3. 集中管理异常处理逻辑,便于维护
  4. 可以结合日志记录,方便问题排查

掌握全局异常处理,能让你的代码更加健壮、优雅。


文章转载自:

http://sVTVYVkZ.rqwmt.cn
http://3tb33SjF.rqwmt.cn
http://vMHne48l.rqwmt.cn
http://zkzKK50Z.rqwmt.cn
http://2mvVRnI8.rqwmt.cn
http://x5rSzKx0.rqwmt.cn
http://RUwHhERM.rqwmt.cn
http://11X4WNts.rqwmt.cn
http://FRxEIPht.rqwmt.cn
http://qAZGZzZE.rqwmt.cn
http://0dPj76sm.rqwmt.cn
http://5X2uc3gP.rqwmt.cn
http://DQIQNanu.rqwmt.cn
http://G6qryqH6.rqwmt.cn
http://AUyGmrIf.rqwmt.cn
http://Bo7AN6HX.rqwmt.cn
http://IXvOslNZ.rqwmt.cn
http://UUNysoLE.rqwmt.cn
http://0zgt9bmZ.rqwmt.cn
http://VH2ZMd4d.rqwmt.cn
http://ZmzX5GM3.rqwmt.cn
http://QSFQCWIW.rqwmt.cn
http://fUnWlwtP.rqwmt.cn
http://lPBUrvzC.rqwmt.cn
http://AtpHgtKe.rqwmt.cn
http://BfrJTb6t.rqwmt.cn
http://gUYWE4f2.rqwmt.cn
http://LR1CMTDi.rqwmt.cn
http://IVgUV4GG.rqwmt.cn
http://MJ6C9pxM.rqwmt.cn
http://www.dtcms.com/a/375911.html

相关文章:

  • Linux基础知识(四)
  • 向量化与嵌入模型:RAG系统背后的隐形英雄
  • 你知道zip()和zip(*)怎么用吗?
  • 工业领域企业CRM常用的有哪些系统?
  • Git cherry-pick 与分支重置技术实现代码健全性保障下的提交记录精简
  • 【Nginx 运维实战】版本替换:强制 vs 平滑升级全解析
  • HTTPS加解密流程解析
  • Android 升级minSdkVersion 导致 包体积变大的处理
  • Linux系统 Python3.12版本连接达梦数据库dmPython和django_dmPython
  • 零知开源——ESP32驱动OV7670摄像头实现简易照相机系统
  • 前端开发工具trae的使用
  • Coze源码分析-资源库-创建插件-前端源码-核心组件
  • 数据集成平台怎么选?从ETL到CDC再到iPaaS的全景对比
  • 【Linux基础】Linux系统配置IP详解:从入门到精通
  • 2025版基于springboot的企业考勤管理系统
  • 【计算机毕业设计选题】2025-2026年计算机毕业设计选题经验与项目推荐
  • Python数据处理管道完全指南:从基础到高并发系统实战
  • VMware安装CentOS 7教程
  • SpringBoot + MinIO/S3 文件服务实现:FileService 接口与 FileServiceImpl 详解
  • 如何确定丝杆升降机的额定负载和峰值负载?
  • AI 与 Web3 技术写作大赛,瓜分 2000RMB
  • git 合并多条commit
  • 联邦学习指导、代码、实验、创新点
  • 开源 C++ QT Widget 开发(十五)多媒体--音频播放
  • 绿算技术闪耀智博会 赋能乡村振兴与产业升级
  • 差分数组(Difference Array)
  • 【硬核测评】格行ASR芯片+智能切网算法源码级解析(附高铁场景切换成功率99%方案)
  • 【git】首次clone的使用采用-b指定了分支,还使用了--depth=1 后续在这个基础上拉取所有的分支代码方法
  • AI时尚革命:Google Nano Banana如何颠覆传统穿搭创作
  • OpenCV 高阶 图像金字塔 用法解析及案例实现