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

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

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

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

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

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

实现步骤:

1 创建自定义异常类

2 创建全局异常处理器,使用@ControllerAdvice注解

3 在处理器类中定义异常处理方法,使用@ExceptionHandler注解指定处理的异常类型

4 在异常处理方法中定义异常响应的格式和内容

三、具体实现

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

java 复制代码
// 用户未找到异常
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 创建全局异常处理器

java 复制代码
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状态码为404
    public Result<Void> handleUserNotFoundException(UserNotFoundException e) {
        return Result.error(404, e.getMessage());
    }
    
    // 处理数据验证异常
    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)  // 设置HTTP状态码为400
    public Result<Void> handleValidationException(ValidationException e) {
        return Result.error(400, e.getMessage());
    }
    
    // 处理其他未捕获的异常
    @ExceptionHandler(Exception.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)  // 设置HTTP状态码为500
    public Result<Void> handleOtherExceptions(Exception e) {
        // 实际项目中可以在这里记录日志
        return Result.error(500, "服务器内部错误:" + e.getMessage());
    }
}

3 在控制器中使用

java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {
    
    @Autowired
    private 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);
    }
    
    @PostMapping
    public 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. 结合日志记录:

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

六、总结

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

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

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

相关推荐
云和数据.ChenGuang1 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
摇滚侠1 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 12
java·数据库·笔记
Cosolar3 小时前
不收费、不加水印、数据归你:我做了个开源的在线简历工具
后端·面试·前端框架
silvamux_3 小时前
10款模型写种草笔记:可发布性、返工来源与成本数据缺口复盘
java·数据库·笔记
步行cgn4 小时前
StringHttpMessageConverter 详解:Spring MVC 中字符串读写的默认转换器
java·spring·mvc
摇滚侠4 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 11
java·笔记·python
小蒜学长4 小时前
基于Spring Boot+Vue3的在线医疗咨询系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·在线问诊·在线医疗咨询系统
Deng桑4 小时前
SpringAI写第一个Agent-把工单循环跑起来
java·agent·工具调用·spring ai
陈随易5 小时前
下载神器!Motrix 停更三年后重写回归
前端·后端·程序员
每天一道题5 小时前
CAP、Raft 与多数派:分布式系统如何达成一致?
分布式·后端·微服务