SpringBoot2.0全局异常处理



在实际项目开发中,我们会遇到各种各样的异常,如果我们对这些异常不做处理直接暴露给用户的话,肯定是一种不好的体验,所以我们想办法捕获异常。最常见的方法是用try-catch 来捕获异常并设置返回信息,但是我们如果每个异常都去try-catch的话,无异是一件很费力的事情,所以我们有必要寻找一个可以处理全局异常的方法…

使用工具

  • IntelliJ IDEA 2018.1 x64
  • jdk8
  • SpringBoot 2.0.3

添加依赖

1
2
3
4
5
6
7
8
9
10
11
dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

创建异常返回信息模板ErrorResponseEntity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author :mathias
* Description: 异常信息模板
* Date: 2018/6/19
*/
public class ErrorResponseEntity {
private int code;
private String msg;

public ErrorResponseEntity(int code, String msg) {
this.code = code;
this.msg = msg;
}

--省略setter、getter方法
}

创建自定义异常TestException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author :mathias
* Description:自定义异常
* Date: 2018/6/19
*/

public class TestException extends RuntimeException{

private int code ;

public TestException(int code, String message) {
super(message);
this.setCode(code);
}

--省略setter、getter方法
}

创建全局处理异常GlobalExceptionHandler

注解说明

-@ControllerAdvice捕获Controller层抛出的异常,如果添加@ResponseBody返回信息则为JSON格式。
-@RestControllerAdvice相当于 @ControllerAdvice 与 @ResponseBody的结合体。
-@ExceptionHandler统一处理一种类的异常,减少代码重复率,降低复杂度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* @author :mathias
* Description: 全局异常处理
* Date: 2018/6/19
*/
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

/**
* 定义要捕获的异常,多个异常用 @ExceptionHandler({})
* @param request
* @param e
* @param response
* @return 响应结果
*/
@ExceptionHandler(TestException.class)
public ErrorResponseEntity testExceptionHandler(HttpServletRequest request,
final Exception e ,
HttpServletResponse response){
response.setStatus(HttpStatus.BAD_REQUEST.value());
RuntimeException exception = (RuntimeException) e;
return new ErrorResponseEntity(400,exception.getMessage());
}
/**
* 定义要捕获的异常,多个异常用 @ExceptionHandler({})
* @param request
* @param e
* @param response
* @return 响应结果
*/
@ExceptionHandler(RuntimeException.class)
public ErrorResponseEntity runtimeException(HttpServletRequest request,
final Exception e ,
HttpServletResponse response){
response.setStatus(HttpStatus.BAD_REQUEST.value());
RuntimeException exception = (RuntimeException) e;
return new ErrorResponseEntity(400,exception.getMessage());
}

/**
* 通用接口映射处理异常
* @param ex
* @param body
* @param headers
* @param status
* @param request
* @return
*/
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex,
Object body,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
if (ex instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException exception = (MethodArgumentNotValidException) ex;
return new ResponseEntity<>(new ErrorResponseEntity(status.value(),
exception.getBindingResult().getAllErrors().get(0).getDefaultMessage()), status);
}
if (ex instanceof MethodArgumentTypeMismatchException) {
MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) ex;
logger.error("参数转换失败,方法:" + exception.getParameter().getMethod().getName()
+ ",参数:" + exception.getName()
+ ",信息:" + exception.getLocalizedMessage());
return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
}
return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
}
}

测试

创建TestController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author :mathias
* Description:测试全局异常
* Date: 2018/6/19
*/
@RestController
public class TestController {
@RequestMapping("/testException")
public String testException(Integer num ){
if (num == null){
throw new TestException(400,"num 不能为空");
}
int i = 10 / num;
return "result: "+ i;
}
}

这里当num = null的时候就抛出我们的自定义异常,然后全局异常捕获,返回我们异常模板的信息。启动项目,访问http://localhost:8080/testException,返回结果

1
2
3
4
{
"code": 400,
"msg": "num 不能为空"
}

再访问 http://localhost:8080/testException?num=0,返回结果

1
2
3
4
{
"code": 400,
"msg": "/ by zero"
}

访问 http://localhost:8080/testException?num=2,返回结果

1
result: 5

好了,这样就完成了我们的全局异常处理。

结尾

文章参考自 http://blog.battcn.com/2018/06/01/springboot/v2-other-exception/

-------------本文结束感谢您的阅读-------------