在做前后端分離的項目時,后端通常都會拆分成多個獨立的微服務,這時候就會涉及每個服務返回給前端的數據格式問題了。下面就來實現一個比較常用的數據格式,統一所有服務的返回值格式。
一般返回的數據格式會包括4個部分,第一部分: 請求處理是否成功,第二部分:服務處理結果編碼,第三部分:編碼對應的文本信息,第四部分:返回值。如下所示:
{
"result": true,
"code": 1000,
"message": "SUCCESS",
"data": {
"lantian": 17,
"qingfen": 16,
"baiyun": 18
}
}
對于異常處理情況,我們也需要統一成上面的格式。如果我們在controller中通過try catch來處理異常的話,會出現一個問題就是每個函數里都加一個Try catch,代碼會變的很亂。下面我們就通過spring boot的注解來省略掉controller中的try-catch 幫助我們來封裝異常信息并返回給前端,這樣用戶也不會得到一些奇奇怪怪的錯誤提示。
{
"result": false,
"code": 3000,
"message": "THIS IS AN UNKNOW EXCEPTION",
"data": null
}
1:定義返回值結構信息(get, set函數省略)
public class CallResultMsg<T> {
private boolean result;
private int code;
private String message;
private T data;
}
2:定義返回值和對應code的信息(get, set函數省略)
public enum CodeAndMsg {
SUCCESS(1000, "SUCCESS"),
METHODFAIL(2000, "ENCOUNTER AN ERROR WHEN EXECUTE METHOD"),
UNKNOWEXCEPTION(3000, "THIS IS AN UNKNOW EXCEPTION");
private int code;
private String msg;
CodeAndMsg(int code, String msg){
this.code = code;
this.msg = msg;
}
}
3:自定義異常
對于一些特別的異常,我們可以自定義Exception和Error Code,這里自定義一個異常(需要繼承RuntimeException)
public class UserDefinedException extends RuntimeException {
private CodeAndMsg exception;
public UserDefinedException(CodeAndMsg exception){
this.exception = exception;
}
public CodeAndMsg getException() {
return exception;
}
public void setException(CodeAndMsg exception) {
this.exception = exception;
}
}
4:RestControllerAdvice來捕獲全局異常,
@RestControllerAdvice都是對Controller進行增強的,可以全局捕獲spring mvc拋的異常。
@ExceptionHandler(value = Exception.class)
ExceptionHandler的作用是用來捕獲指定的異常。
@RestControllerAdvice(annotations = RestController.class)
public class UniformReponseHandler<T> {
@ResponseStatus(HttpStatus.OK)
public CallResultMsg sendSuccessResponse(){
return new CallResultMsg(true, CodeAndMsg.SUCCESS, null);
}
@ResponseStatus(HttpStatus.OK)
public CallResultMsg sendSuccessResponse(T data) {
return new CallResultMsg(true, CodeAndMsg.SUCCESS, data);
}
@ExceptionHandler(UserDefinedException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public CallResultMsg sendErrorResponse_UserDefined(Exception exception){
return new CallResultMsg(false, ((UserDefinedException)exception).getException(), null);
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public CallResultMsg sendErrorResponse_System(Exception exception){
if (exception instanceof UserDefinedException) {
return this.sendErrorResponse_UserDefined(exception);
}
return new CallResultMsg(false, CodeAndMsg.UNKNOWEXCEPTION, null);
}
}
通過上面的一波操作,我們的controller中就不需要再去寫大量的try-catch了,RestControllerAdvice會自動幫助catch,并匹配相應的ExceptionHandler,然后重新封裝異常信息,返回值,統一格式返回給前端。
5:ControllerAdvice 和 RestControllerAdvice的區別
@ControllerAdvice 和 @RestControllerAdvice都是對Controller進行增強的,可以全局捕獲spring mvc拋的異常。
RestControllerAdvice = ControllerAdvice + ResponseBody
6:測試統一異常捕獲功能
@GetMapping("/doTestObject")
public CallResultMsg testObjectReturn(){
Map<String, Integer> map = new HashMap();
map.put("qingfen", 16);
map.put("lantian", 17);
map.put("baiyun", 18);
return new UniformReponseHandler<Map>().sendSuccessResponse(map);
}
@GetMapping("/doTestException/{x}")
public int testExceptionResturn(@PathVariable int x){
if (0 < x && x < 10){
throw new UserDefinedException(CodeAndMsg.METHODFAIL);
} else {
return 1/0;
}
}
返回結果:
{
"result": true,
"code": 1000,
"message": "SUCCESS",
"data": {
"lantian": 17,
"qingfen": 16,
"baiyun": 18
}
}
{
"result": false,
"code": 2000,
"message": "ENCOUNTER AN ERROR WHEN EXECUTE METHOD ",
"data": null
}