一、为什么需要全局异常处理在传统的Spring Boot项目中每个Controller都需要写大量的try-catch来处理异常代码重复、可维护性差。全局异常处理通过ControllerAdviceExceptionHandler统一拦截所有异常将业务逻辑与异常处理解耦。本文将带你从零搭建一套完整的全局异常处理架构包含统一响应体、自定义业务异常、参数校验异常处理、生产级日志链路等直接复制可用。二、统一响应体定义先定义一个标准的API返回格式让前端统一解析Data NoArgsConstructor AllArgsConstructor public class ApiResultT { private int code; private String message; private T data; public static T ApiResultT success(T data) { return new ApiResult(200, success, data); } public static T ApiResultT error(int code, String message) { return new ApiResult(code, message, null); } }三、自定义业务异常定义业务异常类区分系统异常和业务逻辑异常Getter public class BusinessException extends RuntimeException { private final int code; private final String message; public BusinessException(int code, String message) { super(message); this.code code; this.message message; } public BusinessException(ErrorCode errorCode) { this(errorCode.getCode(), errorCode.getMessage()); } }四、全局异常处理器核心类统一处理所有异常类型Slf4j RestControllerAdvice public class GlobalExceptionHandler { // 业务异常 ExceptionHandler(BusinessException.class) public ApiResult? handleBusiness(BusinessException e) { log.warn(业务异常: code{}, msg{}, e.getCode(), e.getMessage()); return ApiResult.error(e.getCode(), e.getMessage()); } // 参数校验异常 ExceptionHandler(MethodArgumentNotValidException.class) public ApiResult? handleValidation(MethodArgumentNotValidException e) { String msg e.getBindingResult().getFieldErrors().stream() .map(err - err.getField() : err.getDefaultMessage()) .collect(Collectors.joining(, )); return ApiResult.error(400, msg); } // 参数类型不匹配 ExceptionHandler(ConstraintViolationException.class) public ApiResult? handleConstraint(ConstraintViolationException e) { return ApiResult.error(400, e.getMessage()); } // 404 ExceptionHandler(NoHandlerFoundException.class) public ApiResult? handleNotFound(NoHandlerFoundException e) { return ApiResult.error(404, 接口不存在); } // 顶级异常兜底 ExceptionHandler(Exception.class) public ApiResult? handleException(Exception e) { log.error(系统异常: , e); return ApiResult.error(500, 服务器繁忙请稍后重试); } }五、错误码枚举Getter AllArgsConstructor public enum ErrorCode { // 通用 PARAM_ERROR(400, 参数错误), UNAUTHORIZED(401, 未登录), FORBIDDEN(403, 无权限), NOT_FOUND(404, 资源不存在), SYSTEM_ERROR(500, 系统异常), // 业务 USER_NOT_EXIST(1001, 用户不存在), USER_PASSWORD_ERROR(1002, 密码错误), ORDER_NOT_FOUND(2001, 订单不存在), ORDER_STATUS_ERROR(2002, 订单状态异常); private final int code; private final String message; }六、在Controller中使用RestController RequestMapping(/user) public class UserController { GetMapping(/{id}) public ApiResultUser getUser(PathVariable Long id) { if (id null || id 0) { throw new BusinessException(ErrorCode.PARAM_ERROR); } User user userService.findById(id); if (user null) { throw new BusinessException(ErrorCode.USER_NOT_EXIST); } return ApiResult.success(user); } PostMapping public ApiResultVoid createUser(Valid RequestBody UserCreateRequest request) { userService.create(request); return ApiResult.success(null); } }七、生产环境建议日志链路在全局异常中加入traceId配合MDC实现全链路追踪告警通知针对500系统异常接入钉钉/企微机器人告警敏感信息过滤生产环境不返回堆栈信息只返回codemessage国际化支持通过Accept-Language返回对应语言的错误信息单元测试为每个异常处理逻辑编写测试用例确保覆盖率这套架构我已经在多个生产项目中验证过从单体应用到微服务都能直接套用。如果你有更好的实践欢迎在评论区分享交流。