👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主
⛪️ 个人社区:个人社区
💞 个人主页:个人主页
🙉 专栏地址: ✅ Java 中级
🙉八股文专题:剑指大厂,手撕 Java 八股文
文章目录
- Spring Boot 如何优雅捕捉异常?
- 1. 全局异常处理器
- 2. 控制器特定的异常处理器
- 3. 使用 `@ControllerAdvice` 进行集中式异常处理
- 4. 自定义异常
- 5. 统一错误响应格式
- 6. 日志记录
- 写在最后
Spring Boot 如何优雅捕捉异常?
在Spring Boot中,优雅地捕捉和处理异常可以提高应用程序的健壮性和用户体验。Spring Boot提供了多种方式来处理异常,包括全局异常处理器、控制器特定的异常处理器以及使用@ControllerAdvice
注解的集中式异常处理。
1. 全局异常处理器
你可以创建一个全局异常处理器来捕获整个应用中的异常。这通常通过实现HandlerExceptionResolver
接口或继承ResponseEntityExceptionHandler
类来完成。
使用 ResponseEntityExceptionHandler
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = { IllegalArgumentException.class })
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException ex) {
ErrorResponse error = new ErrorResponse("Invalid input", ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(value = { RuntimeException.class })
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
ErrorResponse error = new ErrorResponse("Internal server error", ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// 自定义错误响应类
class ErrorResponse {
private String message;
private String details;
public ErrorResponse(String message, String details) {
this.message = message;
this.details = details;
}
// Getters and setters
}
2. 控制器特定的异常处理器
你也可以在单个控制器内定义异常处理器方法,只处理该控制器内的异常。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
@RequestMapping("/api/users")
public class UserController {
@RequestMapping("/get")
public User getUser() {
// 业务逻辑
if (someCondition) {
throw new IllegalArgumentException("Invalid user ID");
}
return new User();
}
@ExceptionHandler(value = { IllegalArgumentException.class })
public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException ex) {
ErrorResponse error = new ErrorResponse("Invalid input", ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
}
3. 使用 @ControllerAdvice
进行集中式异常处理
@ControllerAdvice
是 Spring 提供的一个注解,用于定义全局异常处理类。这个类可以包含多个 @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;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = { IllegalArgumentException.class })
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleIllegalArgumentException(IllegalArgumentException ex) {
return new ErrorResponse("Invalid input", ex.getMessage());
}
@ExceptionHandler(value = { RuntimeException.class })
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleRuntimeException(RuntimeException ex) {
return new ErrorResponse("Internal server error", ex.getMessage());
}
}
// 自定义错误响应类
class ErrorResponse {
private String message;
private String details;
public ErrorResponse(String message, String details) {
this.message = message;
this.details = details;
}
// Getters and setters
}
4. 自定义异常
为了更好地控制异常处理,你可以创建自定义异常类,并在需要的地方抛出这些异常。
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
然后在全局异常处理器中处理这些自定义异常:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = { ResourceNotFoundException.class })
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex) {
return new ErrorResponse("Resource not found", ex.getMessage());
}
// 其他异常处理器
}
5. 统一错误响应格式
为了保持一致性,建议定义一个统一的错误响应格式。这样客户端可以更容易地解析和处理错误信息。
public class ErrorResponse {
private int status;
private String message;
private String details;
public ErrorResponse(int status, String message, String details) {
this.status = status;
this.message = message;
this.details = details;
}
// Getters and setters
}
6. 日志记录
在异常处理器中添加日志记录,以便于调试和监控。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(value = { RuntimeException.class })
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleRuntimeException(RuntimeException ex) {
logger.error("Unexpected error occurred: ", ex);
return new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Internal server error", ex.getMessage());
}
// 其他异常处理器
}
写在最后
通过上述方法,你可以在Spring Boot应用中优雅地捕捉和处理异常。使用@ControllerAdvice
可以集中管理异常处理逻辑,而自定义异常和统一的错误响应格式则有助于提高代码的可维护性和一致性。同时,日志记录对于调试和监控也非常重要。
精彩专栏推荐订阅:在下方专栏👇🏻
✅ 2023年华为OD机试真题(A卷&B卷)+ 面试指导
✅ 精选100套 Java 项目案例
✅ 面试需要避开的坑(活动)
✅ 你找不到的核心代码
✅ 带你手撕 Spring
✅ Java 初阶