【AgileTC】_捕获异常并返回相应自定义状态码
创建一个全局异常捕捉器,捕捉SpringMVC容器中出现的一些特定异常,然后向前端返回更加详细的异常信息,也就是说Filter等非SpringMVC容器中出现的异常并不会被捕获;如果一个异常被该捕捉器捕获了,后端返回的http状态码并不是5类,而是2类;
1.创建一个异常捕捉器类,用@ControllerAdvice注解和@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
public class ExpHandler {
private final static Logger LOGGER = LoggerFactory.getLogger(ExpHandler.class);
(IllegalArgumentException.class)
public Response<?> handlerException(IllegalArgumentException e) {
e.printStackTrace();
LOGGER.error(StatusCode.INTERNAL_ERROR.getCode(), e.getMessage());
return Response.build(StatusCode.INTERNAL_ERROR, e.getMessage());
}
(MissingServletRequestParameterException.class)
public Response<?> handlerException(MissingServletRequestParameterException e) {
e.printStackTrace();
LOGGER.error(StatusCode.INTERNAL_ERROR.getCode(), e.getMessage());
return Response.build(StatusCode.INTERNAL_ERROR, e.getMessage());
}
(JsonMappingException.class)
public Response<?> handlerException(JsonMappingException e) {
e.printStackTrace();
LOGGER.error(StatusCode.JSON_FORMAT_ERROR.getCode(), e.getMessage());
return Response.build(StatusCode.JSON_FORMAT_ERROR);
}
(JsonParseException.class)
public Response<?> handlerException(JsonParseException e) {
e.printStackTrace();
LOGGER.error(StatusCode.DATA_FORMAT_ERROR.getCode(), e.getMessage());
return Response.build(StatusCode.DATA_FORMAT_ERROR);
}
/**
* 自定义异常
*/
(CaseServerException.class)
public Response<?> handlerException(CaseServerException e) {
e.printStackTrace();
LOGGER.error(StatusCode.INTERNAL_ERROR.getCode(), e.getMessage());
return Response.build(StatusCode.INTERNAL_ERROR, e.getMessage());
}
/**
* 这里的全局异常是捕捉controller下没有try catch Exception的Method的
*/
(Exception.class)
public Response<?> handlerException(Exception e) {
e.printStackTrace();
LOGGER.error(StatusCode.SERVER_BUSY_ERROR.getCode(), e.getMessage());
return Response.build(StatusCode.SERVER_BUSY_ERROR);
}
}2.创建一个继承RuntimeException的自定义异常类,其实就是给运行时异常加上一个Status状态码属性,使得捕捉器在捕获到该异常时,可以返回更加详细的信息:
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
37public class CaseServerException extends RuntimeException {
private Status status;
public CaseServerException(Status status) {
this.status = status;
}
public CaseServerException(String message, Status status) {
super(message);
this.status = status;
}
public CaseServerException(String message, Throwable cause, Status status) {
super(message, cause);
this.status = status;
}
public CaseServerException(Throwable cause, Status status) {
super(cause);
this.status = status;
}
public CaseServerException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Status status) {
super(message, cause, enableSuppression, writableStackTrace);
this.status = status;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}3.指定相关场景下抛出对应异常信息,一般这些抛出异常的代码都是在service层中编写,因为一般也就是service层中才会出现各种逻辑错误,往上抛就正好抛到SpringMVC容器的controller层中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//如果角色是基本角色且角色名称被修改了,则报错提示基础角色不能被修改
if (role.getType() > 0 && !request.getRoleName().equals(role.getRoleName())) {
throw new CaseServerException("系统角色名称不得被修改",StatusCode.INTERNAL_ERROR);
}else {
role.setRoleName(request.getRoleName());
}
//如果修改了基础角色的权限则报错
if (role.getType() != 0) {
for (Long inputPermId : inputPermIds) {
if (!dbPermIds.contains(inputPermId)) {
throw new CaseServerException("系统角色权限不得被修改",StatusCode.INTERNAL_ERROR);
}
}
for (Long dbPermId : dbPermIds) {
if (!inputPermIds.contains(dbPermId)) {
throw new CaseServerException("系统角色权限不得被修改",StatusCode.INTERNAL_ERROR);
}
}
}4.访问相关接口时如果出现对应逻辑错误,服务器就会抛出相关异常,并返回对应响应状态码,前端应将该响应信息渲染在浏览器界面上:
1
2
3
4
5
6
7
8
9
10
11
12
13//第一种情况返回的响应体
{
"code": 10400,
"msg": "系统角色名称不得被修改",
"data": null
}
//第二种情况返回的响应体
{
"code": 10400,
"msg": "系统角色权限不得被修改",
"data": null
}