背景
我们知道,当前端请求的后端程序抛出异常时,此时的 http 状态码变成了 500,并有一大串错误信息。今天要做的是整合后台返回信息,不管后台程序有异常,都能返回一个统一格式的信息,前端根据里面的信息来判断是否请求失败。
定义一下正常返回的信息如下:
1
2
3
4
5
6
7
|
{
code:1,
msg:"请求成功", //或其他自定义信息
data:{
//这里存储这个接口的返回信息
}
}
|
错误的信息如下:
1
2
3
4
5
|
{
code:-1, //可以根据不同的情况返回不同的状态码
msg:"请求失败", //或其他自定义信息
data:{}
}
|
实现
在 spring 框架下,这个要求我们可以利用 aop 去实现它,比如对我们所有的接口进行一个横切,对返回信息遇到异常后进行处理。
在 springboot 框架下,已经有现成的东西让我们可以直接去使用了。那就直接上代码了。
定义返回信息实体类:
1
2
3
4
5
6
7
8
|
@Data
public class ResultBean<T> {
private String code;
private String msg;
private T data;
}
|
然后定义一个自定义异常,必须继承自RuntimeException
。如果直接继承Exception
则事务不一定回滚
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
|
@Data
public class AppException extends RuntimeException {
/**
* 异常状态码
*/
private String code;
/**
* 异常提示信息
*/
private String msg;
public AppException(ResultEnums resultEnums) {
super(resultEnums.getMsg());
this.code = resultEnums.getCode();
this.msg = resultEnums.getMsg();
}
public AppException(String msg) {
super(msg);
this.code = "-1";
this.msg = msg;
}
}
|
由于异常信息较多,为了便于管理,我们定义一个枚举
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public enum ResultEnums {
SUCCESS("1", "成功!"),
FAIL("-1", "失败!");
private String code;
private String msg;
ResultEnums(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
|
为了不再每一个返回信息和处理异常都使用 new 一个返回信息类,定义一个工具类来进行处理
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
|
public class ResultUtil {
/**
* 固定成功提示,不返回信息
*
* @return resultBean
*/
public static ResultBean success() {
return success(null);
}
/**
* 固定成功提示,返回信息
*
* @param object 具体信息
* @return resultBean
*/
public static ResultBean success(Object object) {
ResultBean result = new ResultBean();
result.setCode(ResultEnums.SUCCESS.getCode());
result.setMsg(ResultEnums.SUCCESS.getMsg());
result.setData(object);
return result;
}
/**
* 自定义成功提示,返回信息
*
* @param resultEnums
* @param object
* @return
*/
public static ResultBean success(ResultEnums resultEnums, Object object) {
ResultBean result = new ResultBean();
result.setCode(resultEnums.getCode());
result.setMsg(resultEnums.getMsg());
result.setData(object);
return result;
}
/**
* 失败
*
* @param code 错误码
* @param message 错误信息
* @return resultBean
*/
public static ResultBean fail(String code, String message) {
ResultBean result = new ResultBean();
result.setCode(code);
result.setMsg(message);
result.setData(null);
return result;
}
public static ResultBean fail(ResultEnums resultEnums) {
ResultBean result = new ResultBean();
result.setCode(resultEnums.getCode());
result.setMsg(resultEnums.getMsg());
result.setData(null);
return result;
}
}
|
然后是最关键的一步:
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
|
@ControllerAdvice
public class ExceptionHandle {
/**
* 捕获异常 针对不同异常返回不同内容的固定格式信息
* 拦截所有的异常,并且返回 json 格式的信息
* @param e 异常
* @return resultBean
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResultBean handle(Exception e) {
if (e instanceof AppException) {
//如果是我们自定义的异常,就直接返回我们异常里面设置的信息
AppException appException = (AppException) e;
return ResultUtil.fail(appException.getCode(), appException.getMessage());
} else if (e instanceof HttpRequestMethodNotSupportedException) {
//对其他的异常进行处理,如果是请求方法错误,我们设置 code 和 msg 进行返回。
return ResultUtil.fail(ResultEnums.REQUEST_PARAMETER_MISSING.getCode(), ResultEnums.REQUEST_PARAMETER_MISSING.getMsg());
} else {
return ResultUtil.fail(ResultEnums.UN_KNOW_ERROR.getCode(), ResultEnums.UN_KNOW_ERROR.getMsg());
}
}
}
|
测试代码
我们新建一个接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@RestController
public class Test {
@GetMapping(value = "/noError")
public Object noError() {
String data = "ok,you are right";
return ResultUtil.success(data);
}
@GetMapping(value = "/hasError")
public Object hasError() {
//对于业务异常我们可以抛出自定义异常
// throw new AppException(ResultEnums.FAIL);
int a = 1 / 0;
//由于 0 不能做除数,所以会抛出异常
return ResultUtil.success(a);
}
}
|
然后我们访问对于的地址,可以看到正常时的信息和遇到异常时的信息在外部格式是一致的,不会因为服务器出现错误就出现 500 的错误了。
@ControllerAdvice 下其他注解
处理@ExceptionHandler 外还有两个注解
这两个注解在此篇文章中不再记录。