1. Background
In the process of writing a program, various exceptions may occur in the program at any time, so how can we handle various exceptions gracefully?
2. Demand
1. Intercept some exceptions in the system and return custom responses.
for example:
An exception occurs in the system HttpRequestMethodNotSupportedException
, we need to return the following information.
http status code: return 405
{
code: 自定义异常码,
message: 错误消息
}
2. Implement custom exception interception
Intercept what we wrote ourselves BizException
3. Write some abnormal basic code
1. Import the jar package
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
Notice:
The introduction of spring-boot-starter-validation
is to verify the parameters in the request, and then throw an exception when the parameters are not satisfied.
2. Define a custom exception
public class BizException extends RuntimeException {
public BizException() {
}
public BizException(String message) {
super(message);
}
public BizException(String message, Throwable cause) {
super(message, cause);
}
public BizException(Throwable cause) {
super(cause);
}
public BizException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
3. Write a simple control layer
@RestController
@RequestMapping("exception")
public class ExceptionTestController {
static class Req {
@NotBlank
public String password;
}
@PostMapping("password")
public String checkPassword(@Validated @RequestBody Req req) {
if (Objects.equals(req.password, "exception")) {
throw new BizException("密码传递的是exception字符串");
}
return "当前密码,password: " + req.password;
}
}
Explain <br>Provide a /exception/password
api, need to pass a password
parameter
1. MethodArgumentNotValidException will be thrown when the password parameter is not passed.
2. When the password passes the exception parameter, a BizException is thrown.
4. Test
1. What is the response if the password parameter is not passed?
1. Use the default DefaultHandlerExceptionResolver to handle
This class DefaultHandlerExceptionResolver
is auto-configured by default.
从上图中可以看出有一个默认字段的返回值
2. Use ResponseEntityExceptionHandler to handle
1. Write exception handling code - use default logic
@RestControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// 此处自定义返回值
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
}
It can be seen that the handleMethodArgumentNotValid
method directly calls the method of the parent class, that is, the default processing method is used.
从上图中可以看出返回值是空
2. Write exception handling code - return value to return custom content
@Component
@RestControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
// 此处自定义返回值
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
Set<HttpMethod> supportedMethods = ex.getSupportedHttpMethods();
// 自定义请求返回值
Map<String, Object> body = new HashMap<>(4);
body.put("code", "错误码");
body.put("message", "当前请求的方法不支持,支持的请求方法为:" + supportedMethods);
return new ResponseEntity<>(body, headers, status);
}
}
As can be seen from the above code handleHttpRequestMethodNotSupported
method returns a custom body.
从上图中可以看出,返回了我们自己定义的返回值。
2. The password parameter passes the exception
1. Use ResponseEntityExceptionHandler or DefaultHandlerExceptionResolver to handle
由上图可知返回结果不对,我们需要自定义返回结果。
2. Return custom exception
1. Write BizException handling code
@RestControllerAdvice
public class BizExceptionHandler {
@ExceptionHandler(BizException.class)
public ResponseEntity<Object> handleBizException(BizException exception) {
// 自定义请求返回值
Map<String, Object> body = new HashMap<>(4);
body.put("code", "错误码");
body.put("message", "异常信息为:" + exception.getMessage());
return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
2. The test returns the result
从上图可知返回了自定义信息
Fourth, matters needing attention
1. If you implement custom exception handling
- Use
@RestControllerAdvice
annotation on the class - The method uses
@ExceptionHandler
to handle specific exceptions
2. ResponseEntityExceptionHandler handles those exceptions by default
3. After using ResponseEntityExceptionHandler, why is the return body empty after an exception occurs?
By default, after implementing ResponseEntityExceptionHandler
this class, the response result of all exceptions handled by this class is null
, if we want to return other values, we need to deal with them ourselves.
V. Summary
1. If we want to handle custom exceptions, we can use @RestControllerAdvice
|| @ControllerAdvice
configure @ExceptionHandler
to use.
2. If we implement ResponseEntityExceptionHandler
to handle exceptions, then the default exception response result is empty. If we want to not be empty, we need to handle it ourselves.
3. By default, standard Spring MVC exceptions are handled by DefaultHandlerExceptionResolver
.
6. Code implementation
https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-exception-handler
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。