如何使用@ControllerAdvice捕获Service类抛出的异常?
用@ControllerAdvice统一捕获Service层异常的最佳实践
当然应该用@ControllerAdvice来统一处理这类异常,这是Spring生态里统一异常处理的标准方案——既能避免在每个Controller方法里重复写try-catch逻辑,还能统一返回给前端的错误格式,让代码更整洁。
不过先提个小问题:你示例里直接抛Exception太宽泛了,建议自定义业务异常,这样能更精准区分不同错误场景,也方便全局处理。下面是具体操作步骤:
1. 自定义业务异常类
先写一个针对“资源不存在”的自定义异常,继承RuntimeException(Spring对RuntimeException的全局捕获更友好,不用在方法上显式声明throws):
public class ItemNotFoundException extends RuntimeException { public ItemNotFoundException(String message) { super(message); } }
2. 修改Service层代码,抛自定义异常
把原来的通用Exception换成自定义异常,同时可以去掉方法上的throws Exception声明:
public Optional<Item> getItemById(Long itemId) { return Optional.of(itemRepository.findById(itemId) .orElseThrow(() -> new ItemNotFoundException("Item with that id doesn't exist"))); }
3. 创建全局异常处理类(@ControllerAdvice)
写一个标注@ControllerAdvice的类,用@ExceptionHandler注解指定要捕获的异常类型,然后返回统一的错误响应:
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice public class GlobalExceptionHandler { // 专门捕获ItemNotFoundException @ExceptionHandler(ItemNotFoundException.class) public ResponseEntity<String> handleItemNotFound(ItemNotFoundException ex) { // 实际项目里建议返回自定义DTO(比如包含错误码、消息、时间戳的对象),这里用简单字符串示例 return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND); } // 扩展:捕获其他通用运行时异常 @ExceptionHandler(RuntimeException.class) public ResponseEntity<String> handleRuntimeException(RuntimeException ex) { return new ResponseEntity<>("服务器内部错误: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } }
额外补充
如果你的项目里有多种业务异常(比如参数错误、权限不足等),可以给每个异常类写对应的@ExceptionHandler方法,或者创建一个通用业务异常父类,统一捕获父类类型,进一步简化代码。
内容的提问来源于stack exchange,提问作者Leobejj
相关产品推荐
相关产品推荐

