您的位置:首页 > 编程语言 > Java开发

SpringBoot中异常处理

2022-04-28 16:04 681 查看

一、背景

在我们编写程序的过程中,程序中可能随时发生各种异常,那么我们如何优雅的处理各种异常呢?

二、需求

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、如果实现自定义异常处理

  1. 类上使用
    @RestControllerAdvice
    注解
  2. 方法上使用
    @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

七、参考文档

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: