13. Spring Boot如何处理异常?如何全局捕获和处理异常?
在Spring Boot中,处理异常是非常重要的,特别是在Web应用中,如何优雅地处理异常并向客户端返回有意义的信息对用户体验至关重要。Spring Boot提供了多种方式来处理异常,支持局部处理和全局处理,下面详细介绍如何在Spring Boot中捕获和处理异常。
1. 在Controller中处理异常
最基本的方式是在Controller方法中通过try-catch
块来捕获和处理异常。这种方式适合处理特定方法中的异常。
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user/{id}")
public ResponseEntity<?> getUserById(@PathVariable Long id) {
try {
User user = userService.findUserById(id);
return ResponseEntity.ok(user);
} catch (UserNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found");
} catch (Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error");
}
}
}
2. 使用@ExceptionHandler
注解处理局部异常
Spring提供了@ExceptionHandler
注解来处理控制器中的特定异常。使用@ExceptionHandler
注解可以定义一个方法专门处理某种类型的异常。
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user/{id}")
public User getUserById(@PathVariable Long id) {
return userService.findUserById(id);
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found: " + ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGeneralException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error: " + ex.getMessage());
}
}
3. 使用@ControllerAdvice
注解进行全局异常处理
@ControllerAdvice
注解用于定义全局的异常处理逻辑。通过@ControllerAdvice
和@ExceptionHandler
结合,可以在一个类中集中处理应用程序中所有控制器的异常。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found: " + ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGeneralException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal server error: " + ex.getMessage());
}
}
@ControllerAdvice
:用于声明一个类是全局异常处理类,适用于所有的控制器。@ExceptionHandler
:用于指定处理特定异常的方法。
4. 自定义异常类
为了更加精确地处理异常,通常会定义自定义的异常类。例如,定义一个UserNotFoundException
来表示用户未找到的情况。
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
然后在控制器或全局异常处理类中捕获并处理该异常。
5. 使用@ResponseStatus
注解设置HTTP状态码
如果希望在抛出异常时自动返回特定的HTTP状态码,可以在自定义异常类上使用@ResponseStatus
注解。
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
当UserNotFoundException
被抛出时,Spring会自动返回HTTP 404状态码。
6. 使用ResponseEntityExceptionHandler
进行细粒度异常处理
ResponseEntityExceptionHandler
是Spring提供的一个基类,包含了许多针对Spring MVC异常的默认处理逻辑。通过继承这个类,可以覆盖默认的方法,提供更细粒度的异常处理。
@ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
String errorMessage = "Validation failed for object='" + ex.getBindingResult().getObjectName() + "'. Error count: " + ex.getBindingResult().getErrorCount();
return new ResponseEntity<>(errorMessage, headers, status);
}
// 可以覆盖更多的方法以处理其他异常
}
7. JSON格式返回错误信息
在RESTful API中,通常希望返回JSON格式的错误信息,可以通过返回ResponseEntity
来实现。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<Map<String, String>> handleUserNotFoundException(UserNotFoundException ex) {
Map<String, String> response = new HashMap<>();
response.put("error", "User not found");
response.put("details", ex.getMessage());
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, String>> handleGeneralException(Exception ex) {
Map<String, String> response = new HashMap<>();
response.put("error", "Internal server error");
response.put("details", ex.getMessage());
return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
8. 总结
Spring Boot提供了多种方式来处理异常,包括局部处理、全局处理、自定义异常类、使用@ResponseStatus
设置状态码等。通过这些机制,开发者可以有效地管理和处理应用程序中的异常情况,提高应用的健壮性和用户体验。
- 局部异常处理:在控制器方法中直接使用
try-catch
或@ExceptionHandler
。 - 全局异常处理:使用
@ControllerAdvice
结合@ExceptionHandler
进行全局异常处理。 - 自定义异常类:创建自定义异常类,增强异常语义,并结合
@ResponseStatus
设置HTTP状态码。 - 细粒度异常处理:通过继承
ResponseEntityExceptionHandler
来处理Spring MVC中的常见异常。
这些方法可以根据具体应用需求灵活组合使用,确保异常处理的高效和一致性。