一、背景
在咱们编写程序的过程中,程序中可能随时产生各种异样,那么咱们如何优雅的解决各种异样呢?
二、需要
1、拦挡零碎中局部异样,返回自定义的响应。
比方:
零碎产生 HttpRequestMethodNotSupportedException
异样,咱们须要返回如下信息。
http 的状态码:返回 405
{
code: 自定义异样码,
message: 谬误音讯
}
2、实现自定义异样的拦挡
拦挡咱们本人写的 BizException
三、编写一些异样根底代码
1、引入 jar 包
<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>
留神:
引入 spring-boot-starter-validation
是为了验证申请的中的参数,而后当参数不满足时抛出异样。
2、定义一个自定义异样
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、编写一个简略的管制层
@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;
}
}
解释
提供一个 /exception/password
api,须要传递一个 password
参数
1、当不传递 password 参数时将抛出 MethodArgumentNotValidException 异样。
2、当 password 传递 exception 参数时,则抛出 BizException 异样。
4、测试
1、不传递 password 参数响应是什么
1、应用默认的 DefaultHandlerExceptionResolver 解决
这个类 DefaultHandlerExceptionResolver
是默认主动配置的。从上图中能够看出有一个默认字段的返回值
2、应用 ResponseEntityExceptionHandler 解决
1、编写异样解决代码 - 应用默认的逻辑
@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);
}
}
能够看到 handleMethodArgumentNotValid
办法间接调用父类的办法,即应用默认的解决形式。
从上图中能够看出返回值是空
2、编写异样解决代码 - 返回值返回自定义内容
@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);
}
}
由下面的代码可知 handleHttpRequestMethodNotSupported
办法返回了自定义的 body。从上图中能够看出,返回了咱们本人定义的返回值。
2、password 参数传递 exception
1、应用 ResponseEntityExceptionHandler 或 DefaultHandlerExceptionResolver 解决
由上图可知返回后果不对,咱们须要自定义返回后果。
2、返回自定义异样
1、编写 BizException 解决代码
@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、测试返回后果
从上图可知返回了自定义信息
四、注意事项
1、如果实现自定义异样解决
- 类上应用
@RestControllerAdvice
注解 - 办法上应用
@ExceptionHandler
来解决特定的异样
2、ResponseEntityExceptionHandler 默认解决那些异样
3、应用了 ResponseEntityExceptionHandler 后,为什么产生了异样后返回体为空
默认状况下,实现了 ResponseEntityExceptionHandler
这个类后,这个类解决的所有异样的响应后果都是 null
,如果想返回别的值须要咱们本人去解决。
五、总结
1、如果咱们想解决自定义异样,则能够应用 @RestControllerAdvice
|| @ControllerAdvice
配置 @ExceptionHandler
来应用。
2、如果咱们实现了 ResponseEntityExceptionHandler
来解决异样,那么默认的异样的响应后果为空,如果想不为空,则须要咱们本人解决。
3、默认状况下,规范的 Spring MVC 异样会通过 DefaultHandlerExceptionResolver
来解决。
六、代码实现
https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-exception-handler
七、参考文档