前置说明

多余的try catch 很影响项目美观,但是异常又不能不处理,这篇主要讲一下如何在springboot项目中统一处理异常。
此篇因为需要在错误时返回json数据,故引用了Java项目构建基础之统一响应 篇的统一响应。

必要jar包

1
2
3
4
5
6
7
8
9
10
11
12
13
<dependencies>
<!-- spring web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok 简化代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

创建自定义异常

1
2
3
4
5
6
7
8
9
10
11
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
public class ArgumentException extends RuntimeException {
// 这里是统一响应中的状态码与信息
private IResultCode resultCode;
public ArgumentException(IResultCode resultCode,String message){
super(resultCode.getMessage()+message);
this.resultCode = resultCode;
}
}

验证工具类(类似Asserts)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ArgumentUtils {
/**
* 验证参数非null
* <br/>
* @param o 需要验证的变量
* @param resultCode 如果为null时希望接口返回什么
* @author KThirty
* @since 2020/5/22
*/
public static void notNull(@Nullable Object o, IResultCode resultCode,String message){
if(null == o){
throw new ArgumentException(resultCode,message);
}
}
}

异常统一处理

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
@RestControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

/**
* 父类异常处理
*/
@ExceptionHandler(Exception.class)
public R handleException(Exception e){
return R.fail(ResultCode.FAILURE);
}

/**
* 参数异常
*/
@ExceptionHandler(ArgumentException.class)
public R handleArgumentException(ArgumentException e){
return R.fail(e.getResultCode(),e.getMessage());
}

/**
* 空指针异常
*/
@ExceptionHandler(NullPointerException.class)
public R handleNullPointerException(NullPointerException e){
return R.fail(ResultCode.FAILURE,"空指针异常");
}
}

测试请求

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@RequestMapping("/test/param")
public class TestParamController {
@GetMapping("not-null")
public R testParamNotNull(String name){
ArgumentUtils.notNull(name, ResultCode.PARAM_MISS,"name 不可为空");
return R.success();
}
@GetMapping("null-point")
public R testNullPoint(Integer age){
int i = age.intValue();
return R.success();
}
}

步骤

  1. 请求http://localhost:8080/test/param/not-null 返回{"code":400,"success":false,"data":null,"message":"缺少必要的请求参数name 不可为空"}
  2. 请求http://localhost:8080/test/param/not-null?name=test返回{"code":200,"success":true,"data":null,"message":"操作成功"}
  3. 请求http://localhost:8080/test/param/null-point 返回{"code":400,"success":false,"data":null,"message":"空指针异常"}
  4. 请求http://localhost:8080/test/param/null-point?age=1返回{"code":200,"success":true,"data":null,"message":"操作成功"}

总结

使用@RestControllerAdvice@ExceptionHandler 注解实现全局异常处理

改进Asserts抛出自定义异常