缘博客
发布日期

Spring Boot:全局异常处理

作者
  • 姓名
    社交账号

为什么需要统一异常处理

项目运行过程中,Controller、Service、Mapper、数据库都可能出现异常。

如果不处理,Spring Boot 默认可能返回:

{
  "timestamp": "...",
  "status": 500,
  "error": "Internal Server Error",
  "path": "/emps"
}

但项目已经约定统一 Result 响应格式,因此默认异常响应不符合接口规范。


每个Controller都写try-catch的问题

可以直接在 Controller 中捕获异常:

@GetMapping("/{id}")
public Result getInfo(@PathVariable Integer id) {
    try {
        Emp emp = empService.getInfo(id);
        return Result.success(emp);
    } catch (Exception e) {
        return Result.error("对不起,服务器异常,请稍后重试");
    }
}

但如果每个接口都这样写,会产生大量重复代码,Controller 越来越臃肿。


全局异常处理器

更合理的方式是让异常统一交给全局处理器:

Controller
Service
Mapper
Exception
全局异常处理器
统一Result

课程示例:

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler
    public Result handleException(Exception e) {
        log.error("全局异常处理器, 拦截到异常", e);
        return Result.error("对不起,服务器异常,请稍后重试");
    }
}

@RestControllerAdvice

课程给出的关系:

@RestControllerAdvice
=
@ControllerAdvice
+
@ResponseBody

它适合前后端分离项目,可以让异常处理方法的返回值直接作为 HTTP 响应体。


@ExceptionHandler

@ExceptionHandler 声明当前方法用于处理异常。

课程示例直接处理通用的:

Exception

当 Controller 调用链中的异常没有被处理时,就可以进入全局异常处理器。


统一日志与响应

全局处理器中保留异常日志:

log.error("全局异常处理器, 拦截到异常", e);

前端则得到统一、友好的错误结果:

{
  "code": 0,
  "msg": "对不起,服务器异常,请稍后重试",
  "data": null
}

这样业务 Controller 无需反复写 try-catch,同时异常响应格式也能保持统一。