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

Spring Boot全局异常处理:一网打尽Controller层异常,@RestControllerAdvice解析

在Spring Boot应用中,异常处理是构建健壮API的核心环节。

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

在传统Controller开发中,我们经常面临这样的困境:

@RestController
public class UserController {@GetMapping("/users/{id}")public User getUser(@PathVariable Long id) {try {return userService.findById(id);} catch (UserNotFoundException e) {// 重复的异常处理代码return new ErrorResponse("用户不存在");} catch (DatabaseException e) {// 每个Controller都要处理相同异常return new ErrorResponse("数据库错误");}}
}

痛点分析

  • 重复代码遍布各个Controller

  • 异常处理与业务逻辑耦合

  • 响应格式不统一

  • 维护成本高

二、@RestControllerAdvice 

1. 注解关系

2. 核心组件协作

三、Spring Boot 3 全局异常处理实战

1. 基础异常响应封装
public record ErrorResponse(Instant timestamp,int status,String error,String message,String path
) {public ErrorResponse(HttpStatus status, String message, String path) {this(Instant.now(), status.value(), status.getReasonPhrase(), message, path);}
}
2. 核心异常处理器实现
@RestControllerAdvice
public class GlobalExceptionHandler {// 处理自定义业务异常@ExceptionHandler(BusinessException.class)public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex, WebRequest request) {return createResponse(HttpStatus.BAD_REQUEST, ex, request);}// 处理数据不存在异常@ExceptionHandler(EntityNotFoundException.class)public ResponseEntity<ErrorResponse> handleEntityNotFound(EntityNotFoundException ex, WebRequest request) {return createResponse(HttpStatus.NOT_FOUND, ex, request);}// 处理所有未捕获异常@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex, WebRequest request) {return createResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex, request);}// 统一响应构建方法private ResponseEntity<ErrorResponse> createResponse(HttpStatus status, Exception ex, WebRequest request) {String path = ((ServletWebRequest) request).getRequest().getRequestURI();ErrorResponse body = new ErrorResponse(status, ex.getMessage(), path);return ResponseEntity.status(status).body(body);}
}
3. 自定义业务异常
public class BusinessException extends RuntimeException {public BusinessException(String message) {super(message);}
}

四、深度解析异常处理流程

1. 异常处理调用链

2. 异常匹配优先级

五、高级应用场景

1. 处理验证异常(Spring Validation)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ErrorResponse handleValidationExceptions(MethodArgumentNotValidException ex) {Map<String, String> errors = new HashMap<>();ex.getBindingResult().getFieldErrors().forEach(error -> {String fieldName = error.getField();String message = error.getDefaultMessage();errors.put(fieldName, message);});return new ErrorResponse(HttpStatus.BAD_REQUEST,"验证失败",errors);
}
2. 处理安全异常(Spring Security)
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<ErrorResponse> handleAccessDenied(AccessDeniedException ex, WebRequest request) {String path = ((ServletWebRequest) request).getRequest().getRequestURI();ErrorResponse body = new ErrorResponse(HttpStatus.FORBIDDEN,"无权访问此资源",path);return ResponseEntity.status(HttpStatus.FORBIDDEN).body(body);
}

六、性能优化最佳实践

  1. 异常分类处理:精确匹配特定异常,避免使用过于宽泛的Exception.class

  2. 层次化异常结构

    // 基础业务异常
    public abstract class BaseException extends RuntimeException {private final ErrorCode errorCode;public BaseException(ErrorCode errorCode, String message) {super(message);this.errorCode = errorCode;}
    }// 具体业务异常
    public class PaymentException extends BaseException {public PaymentException(String message) {super(ErrorCode.PAYMENT_FAILED, message);}
    }

  3. 异常日志分级

    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex, WebRequest request) {// 业务异常只记录DEBUG日志log.debug("Business exception occurred: {}", ex.getMessage());return createResponse(HttpStatus.BAD_REQUEST, ex, request);
    }@ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex, WebRequest request) {// 未知异常记录ERROR日志log.error("Unexpected error occurred", ex);return createResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex, request);
    }

 七、实战

正常请求

GET /api/users/123
Status: 200 OK
Response: {"id":123,"name":"John Doe"}

 异常请求

GET /api/users/999
Status: 404 Not Found
Response: {"timestamp": "2023-08-20T10:15:30Z","status": 404,"error": "Not Found","message": "用户不存在","path": "/api/users/999"
}

验证失败请求

POST /api/users
Payload: {"name": "", "email": "invalid-email"}
Status: 400 Bad Request
Response: {"timestamp": "2023-08-20T10:18:45Z","status": 400,"error": "Bad Request","message": "验证失败","errors": {"name": "姓名不能为空","email": "邮箱格式不正确"}
}

八、总结

1、@RestControllerAdvice = @ControllerAdvice + @ResponseBody

  • 全局处理控制器异常
  • 响应体自动序列化(JSON/XML)

2、异常处理优先级

  • Controller局部处理器 > 全局处理器
  • 具体异常 > 通用异常

3.最佳实践

// 返回明确HTTP状态码
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(UserNotFoundException.class)// 使用ResponseEntity精确控制响应
@ExceptionHandler(PaymentException.class)
public ResponseEntity<ErrorResponse> handlePaymentException() {// 自定义响应头等复杂操作
}

4、生产环境建议

  • 禁用敏感错误信息(spring.mvc.include-error-details)
  • 自定义错误码体系
  • 异常国际化支持

So, 当再次处理错误时,应该能独挡一面了。当然,业务中,异常还应该有日志记录,如ES,traceInfo, 上下文等信息,便于排错.

 


文章转载自:
http://culpable .alwpc.cn
http://hexadecane .alwpc.cn
http://donghai .alwpc.cn
http://pentene .alwpc.cn
http://chemic .alwpc.cn
http://rosabel .alwpc.cn
http://biometricist .alwpc.cn
http://punter .alwpc.cn
http://paviser .alwpc.cn
http://luteinize .alwpc.cn
http://correctness .alwpc.cn
http://setterwort .alwpc.cn
http://scarlet .alwpc.cn
http://tootle .alwpc.cn
http://tasty .alwpc.cn
http://verbatim .alwpc.cn
http://decollate .alwpc.cn
http://scratchcat .alwpc.cn
http://cero .alwpc.cn
http://meld .alwpc.cn
http://syntheses .alwpc.cn
http://gaffer .alwpc.cn
http://dyschizia .alwpc.cn
http://kindergarten .alwpc.cn
http://capillarity .alwpc.cn
http://hypoglobulia .alwpc.cn
http://fore .alwpc.cn
http://glyphographic .alwpc.cn
http://obligate .alwpc.cn
http://banteng .alwpc.cn
http://www.dtcms.com/a/293939.html

相关文章:

  • 设计模式(单例)
  • 界面组件DevExpress WPF中文教程:Grid - 如何过滤节点?
  • Linux下SVN常用指令
  • 设计模式代码总结
  • Android MediaCodec 的使用和源码实现分析
  • 路由器与交换机的区别
  • 从入门到精通:Windows右键菜单管理全解析
  • 为什么 Linux 启动后还能升级内核?
  • Jmeter的函数助手使用
  • 基于Dapr Sidecar的微服务通信框架设计与性能优化实践
  • 【软件系统架构】系列七:物联网云平台系统性能深入解析
  • HTTP性能优化终极指南:从协议原理到企业级实践
  • 视频、音频录制
  • 操作系统:系统调用的分类(Types of System Calls)
  • C++ 扫描局域网某个端口是否开放(如 5555 )(android adb) 线程并发加速
  • 3d移动translate3d
  • 秋招Day17 - Spring - Spring Boot
  • 【图像处理基石】如何实现一个车辆检测算法?
  • Nginx和Apache的区别
  • 多维任务筛选工具功能解析:如何通过智能筛选功能精准对接任务需求?
  • There are 2 missing blocks. The following files may be corrupted
  • 亚马逊AI新项目Starfish:重构电商Listing生态的机遇与挑战
  • 西班牙智能警示灯法案:引领欧洲智能交通新趋势
  • 0.0 深度学习资料网站
  • 工业控制系统的现状与发展趋
  • 分享一个tauri-plugin-http的工具类
  • python3写一个异步流式 http 接口服务调用大模型(async, stream, sanic)---6.2
  • 基于数据挖掘的短视频点赞影响因素分析【LightGBM、XGBoost、随机森林、smote】
  • 探索大语言模型(LLM):提升 RAG 性能的全方位优化策略
  • 深圳TCL外包岗位要去吗?