SpringMVC全局异常处理及统一结果返回
chen subao Lv1

定义顶级CustomExceptionCustomRuntimeException异常类,可在类里添加其他属性,所有自定义的异常继承CustomExceptionCustomRuntimeException,在全局处理自定义异常时只需处理定义好的两个顶级异常类。

CustomException异常类

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
import lombok.Getter;
import org.springframework.http.HttpStatus;

/**
* 自定义业务顶级异常
*/
@Getter
public class CustomException extends Exception {

private ErrCodeEnum errCode = ErrCodeEnum.UNTREATED_EX;
private HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;

public CustomException() {
super();
}

public CustomException(ErrCodeEnum errCode, HttpStatus status) {
super();
this.errCode = errCode;
this.status = status;
}

public CustomException(String message) {
super(message);
}

public CustomException(String message, ErrCodeEnum errCode) {
super(message);
this.errCode = errCode;
}

public CustomException(String message, ErrCodeEnum errCode, HttpStatus status) {
super(message);
this.errCode = errCode;
this.status = status;
}
}

CustomRuntimeException运行时异常类

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
import lombok.Getter;
import org.springframework.http.HttpStatus;

/**
*自定义业务顶级运行时异常
*/
@Getter
public class CustomRuntimeException extends RuntimeException {

private ErrCodeEnum errCode = ErrCodeEnum.UNTREATED_RE;
private HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;

public CustomRuntimeException() {
super();
}

public CustomRuntimeException(ErrCodeEnum errCode, HttpStatus status) {
super();
this.errCode = errCode;
this.status = status;
}

public CustomRuntimeException(String message) {
super(message);
}

public CustomRuntimeException(String message, ErrCodeEnum errCode) {
super(message);
this.errCode = errCode;
}

public CustomRuntimeException(String message, ErrCodeEnum errCode, HttpStatus status) {
super(message);
this.errCode = errCode;
this.status = 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.fasterxml.jackson.annotation.JsonInclude;

/**
* 统一数据返回格式
* @param <T>
*/
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result<T> {

private Boolean success;
private Integer errCode;
private T data;
private String errMsg;

public static <T> ResponseEntity<Result<T>> success() {
return success((T) null);
}

public static <T> ResponseEntity<Result<T>> success(HttpStatus status) {
return success(null, status);
}

public static <T> ResponseEntity<Result<T>> success(T data) {
return success(data, HttpStatus.OK);
}

public static <T> ResponseEntity<Result<T>> success(T data, HttpStatus status) {
Result<T> result = new Result<T>()
.setSuccess(true)
.setData(data)
.setErrCode(ErrCodeEnum.OK.errCode());
return ResponseEntity.status(status).body(result);
}

public static ResponseEntity<Result<?>> fail(String errMsg) {
return fail(errMsg, ErrCodeEnum.UNTREATED_EX.errCode());
}

public static ResponseEntity<Result<?>> fail(String errMsg, int errCode) {
return fail(errMsg, errCode, HttpStatus.BAD_REQUEST);
}

public static ResponseEntity<Result<?>> fail(String errMsg, int errCode, HttpStatus status) {
Result<?> result = new Result<>()
.setSuccess(false)
.setErrCode(errCode)
.setErrMsg(errMsg);
return ResponseEntity.status(status).body(result);
}
}

定义ErrCode类

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
/**
* 自定义errCode种类
*/
public enum ErrCodeEnum {

/**
* 框架内未经处理的异常
*/
UNTREATED_FRAMEWORK_EX(-1, "未定义的异常"),

/**
* 框架内未经处理的运行时异常
*/
UNTREATED_FRAMEWORK_RE(-2, "未定义的异常"),

/**
* 系统内未经处理的异常
*/
UNTREATED_EX(-1001, "未定义的系统异常"),

/**
* 系统内未经处理的运行时异常
*/
UNTREATED_RE(-1002, "未定义的系统异常"),

/**
* 请求成功
*/
OK(0, "成功");

private final int errCode;
private final String desc;

ErrCodeEnum(int errCode, String desc) {
this.errCode = errCode;
this.desc = desc;
}

public int errCode() {
return this.errCode;
}

public String desc() {
return this.desc;
}
}

GlobalExceptionHandler处理类

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
* 自定义全局异常处理类
*/
@RestControllerAdvice
public class GlobalExceptionHandler {

@Value("${spring.profiles.active}")
private String activeProfile;

@ExceptionHandler(CustomException.class)
public Object customException(CustomException e) {
if ("dev".equals(activeProfile)) {
e.printStackTrace();
}
return Result.fail(e.getMessage(), e.getErrCode().errCode(), e.getStatus());
}

@ExceptionHandler(CustomRuntimeException.class)
public ResponseEntity<?> customRuntimeException(CustomRuntimeException e) {
if ("dev".equals(activeProfile)) {
e.printStackTrace();
}
return Result.fail(e.getMessage(), e.getErrCode().errCode(), e.getStatus());
}

@ExceptionHandler(Exception.class)
public ResponseEntity<?> exception(Exception e) {
if ("dev".equals(activeProfile)) {
e.printStackTrace();
}
return Result.fail(e.getMessage(), ErrCodeEnum.UNTREATED_FRAMEWORK_EX.errCode(), HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<?> runtimeException(RuntimeException e) {
if ("dev".equals(activeProfile)) {
e.printStackTrace();
}
return Result.fail(e.getMessage(), ErrCodeEnum.UNTREATED_FRAMEWORK_RE.errCode(), HttpStatus.INTERNAL_SERVER_ERROR);
}

/**
* spring security中的异常
*/
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<?> accessDeniedException(AccessDeniedException e) {
if ("dev".equals(activeProfile)) {
e.printStackTrace();
}
return Result.fail(e.getMessage(), {ErrCodeEnum.errCode()}, HttpStatus.FORBIDDEN);
}

/**
* spring security中的异常
*/
@ExceptionHandler({BadCredentialsException.class, UsernameNotFoundException.class})
public ResponseEntity<?> usernameNotFoundException(Exception e) {
if ("dev".equals(activeProfile)) {
e.printStackTrace();
}
return Result.fail("用户名或密码错误", {ErrCodeEnum.errCode()}, HttpStatus.BAD_REQUEST);
}

/**
* Controller使用 {@link Validated} 注解参数校验失败后的异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> methodArgumentNotValidException(MethodArgumentNotValidException e) {
if ("dev".equals(activeProfile)) {
e.printStackTrace();
}
FieldError fieldError = exception
.getBindingResult()
.getFieldErrors()
.iterator()
.next();
return Result.fail(fieldError.getDefaultMessage(), {ErrCodeEnum.errCode()}, HttpStatus.BAD_REQUEST);
}

}

{ErrCodeEnum.errCode()}需改成具体的int errCode

示例到此已结束,根据业务需要自行修改

 评论