SpringBoot統(tǒng)一響應(yīng)格式及統(tǒng)一異常處理
在我們開發(fā)SpringBoot后端服務(wù)時(shí),一般需要給前端統(tǒng)一響應(yīng)格式,方便前端調(diào)試及配置錯(cuò)誤提示等等。這篇文章講講實(shí)際工作中統(tǒng)一響應(yīng)格式及統(tǒng)一異常處理是如何做的。
一、統(tǒng)一響應(yīng)基礎(chǔ)類
在項(xiàng)目中對(duì)應(yīng)工具類或Vo層來創(chuàng)建我們的統(tǒng)一響應(yīng)類
ResponseResult
:
import com.fasterxml.jackson.annotation.JsonInclude; import com.zhang.enums.AppHttpCodeEnum; import java.io.Serializable; @JsonInclude(JsonInclude.Include.NON_NULL) public class ResponseResult<T> implements Serializable { private Integer code; private String msg; private T data; public ResponseResult() { this.code = AppHttpCodeEnum.SUCCESS.getCode(); this.msg = AppHttpCodeEnum.SUCCESS.getMsg(); } public ResponseResult(Integer code, T data) { this.code = code; this.data = data; } public ResponseResult(Integer code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public ResponseResult(Integer code, String msg) { this.code = code; this.msg = msg; } public static ResponseResult errorResult(int code, String msg) { ResponseResult result = new ResponseResult(); return result.error(code, msg); } public static ResponseResult okResult() { ResponseResult result = new ResponseResult(); return result; } public static ResponseResult okResult(int code, String msg) { ResponseResult result = new ResponseResult(); return result.ok(code, null, msg); } public static ResponseResult okResult(Object data) { ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getMsg()); if (data != null) { result.setData(data); } return result; } public static ResponseResult errorResult(AppHttpCodeEnum enums) { return setAppHttpCodeEnum(enums, enums.getMsg()); } public static ResponseResult errorResult(AppHttpCodeEnum enums, String msg) { return setAppHttpCodeEnum(enums, msg); } public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums) { return okResult(enums.getCode(), enums.getMsg()); } private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String msg) { return okResult(enums.getCode(), msg); } public ResponseResult<?> error(Integer code, String msg) { this.code = code; this.msg = msg; return this; } public ResponseResult<?> ok(Integer code, T data) { this.code = code; this.data = data; return this; } public ResponseResult<?> ok(Integer code, T data, String msg) { this.code = code; this.data = data; this.msg = msg; return this; } public ResponseResult<?> ok(T data) { this.data = data; return this; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
里面還有用到一個(gè)響應(yīng)的枚舉類AppHttpCodeEnum
,接下來我們創(chuàng)建這個(gè)枚舉類
二、響應(yīng)枚舉類
AppHttpCodeEnum
:
public enum AppHttpCodeEnum { // 成功 SUCCESS(200, "操作成功"), // 登錄 NEED_LOGIN(401, "需要登錄后操作"), NO_OPERATOR_AUTH(403, "無權(quán)限操作"), SYSTEM_ERROR(500, "出現(xiàn)錯(cuò)誤"), USERNAME_EXIST(501, "用戶名已存在"), PHONENUMBER_EXIST(502, "手機(jī)號(hào)已存在"), EMAIL_EXIST(503, "郵箱已存在"), REQUIRE_USERNAME(504, "必需填寫用戶名"), CONTENT_NOT_NULL(506, "評(píng)論內(nèi)容不能為空"), FILE_TYPE_ERROR(507, "文件類型錯(cuò)誤"), USERNAME_NOT_NULL(508, "用戶名不能為空"), NICKNAME_NOT_NULL(509, "昵稱不能為空"), PASSWORD_NOT_NULL(510, "密碼不能為空"), EMAIL_NOT_NULL(511, "郵箱不能為空"), NICKNAME_EXIST(512, "昵稱已存在"), LOGIN_ERROR(505, "用戶名或密碼錯(cuò)誤"); int code; String msg; AppHttpCodeEnum(int code, String errorMessage) { this.code = code; this.msg = errorMessage; } public int getCode() { return code; } public String getMsg() { return msg; } }
一般我們?cè)谶@個(gè)枚舉類中管理需要響應(yīng)的錯(cuò)誤code
及msg
三、統(tǒng)一響應(yīng)格式使用
在對(duì)應(yīng)的controller或者service里面使用統(tǒng)一響應(yīng)類
- 成功:
ResponseResult.okResult()
- 失敗:
ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR)
, 參數(shù)傳入我們定義的響應(yīng)枚舉類
四、統(tǒng)一異常處理
1. 自定義異常
為什么我們需要自定義異常?因?yàn)樵谀承┣闆r下,我們需要返回我們自定義的響應(yīng)格式非常不方便,如在處理用戶鑒權(quán)或token校驗(yàn)的時(shí)候,因?yàn)橄襁@些部分我們一般都是在單獨(dú)的工具類中去處理,這時(shí)候如果報(bào)錯(cuò)其實(shí)就可以拋出我們自定義的異常,交由我們?nèi)值漠惓L幚砣ソy(tǒng)一返回響應(yīng)。
- 在
exception
包下新建SystemException
類 SystemException
繼承RuntimeException
具體實(shí)現(xiàn)代碼如下
exception.SystemException:
import com.jk.enums.AppHttpCodeEnum; public class SystemException extends RuntimeException{ private int code; private String msg; public int getCode() { return code; } public String getMsg() { return msg; } public SystemException(AppHttpCodeEnum appHttpCodeEnum) { super(appHttpCodeEnum.getMsg()); this.code = appHttpCodeEnum.getCode(); this.msg = appHttpCodeEnum.getMsg(); } }
目前只是自定義了異常,我們還需要對(duì)自定義的異常進(jìn)行處理,返回統(tǒng)一的響應(yīng)格式。
2.異常處理
- 在
handler.exception
包下新建GlobalExceptionHandler
處理類 @RestControllerAdvice
是組合注解,由@ControllerAdvice
、@ResponseBody
組成,標(biāo)明是一個(gè)統(tǒng)一異常處理的類,并把返回結(jié)果封裝在ResponseBody
中@Slf4j
是Lombok
實(shí)現(xiàn)日志輸出的注解@ExceptionHandler
標(biāo)明該方法處理哪些異常
具體代碼實(shí)現(xiàn)如下:
handler.exception.GlobalExceptionHandler:
import com.jk.enums.AppHttpCodeEnum; import com.jk.exception.SystemException; import com.jk.vo.ResponseResult; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(SystemException.class) public ResponseResult systemExceptionHandler(SystemException e) { log.error("出現(xiàn)了異常! {}", e); return ResponseResult.errorResult(e.getCode(), e.getMsg()); } @ExceptionHandler(Exception.class) public ResponseResult exceptionHandler(Exception e) { log.error("出現(xiàn)了異常! {}", e); return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage()); } }
可以看到我們除了處理自定義異常SystemException
外,還對(duì)Exception
就是其他我們無法預(yù)料到的異常做了一個(gè)兜底。
3.自定義異常使用
在需要拋出異常的地方:
throw new SystemException(AppHttpCodeEnum.LOGIN_ERROR);
前端接收到的響應(yīng)是:
{ "code": 505, "msg": "用戶名或密碼錯(cuò)誤" }
這樣就比接收到500錯(cuò)誤也不知道錯(cuò)誤原因好多了。
到此這篇關(guān)于SpringBoot統(tǒng)一響應(yīng)格式及統(tǒng)一異常處理的文章就介紹到這了,更多相關(guān)SpringBoot統(tǒng)一響應(yīng)格式及異常處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot獲取前臺(tái)參數(shù)的六種方式以及統(tǒng)一響應(yīng)
- springboot?全局異常處理和統(tǒng)一響應(yīng)對(duì)象的處理方式
- 淺談SpringBoot如何封裝統(tǒng)一響應(yīng)體
- 詳解SpringBoot統(tǒng)一響應(yīng)體解決方案
- 詳解SpringBoot中的統(tǒng)一異常處理
- Springboot項(xiàng)目全局異常統(tǒng)一處理案例代碼
- springboot斷言異常封裝與統(tǒng)一異常處理實(shí)現(xiàn)代碼
- Springboot項(xiàng)目異常處理及返回結(jié)果統(tǒng)一
- SpringBoot接口如何統(tǒng)一異常處理
相關(guān)文章
java 流操作對(duì)文件的分割和合并的實(shí)例詳解
這篇文章主要介紹了java 流操作對(duì)文件的分割和合并的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10mybatis執(zhí)行批量更新batch update 的方法(oracle,mysql兩種)
這篇文章主要介紹了mybatis執(zhí)行批量更新batch update 的方法,提供oracle和mysql兩種方法,非常不錯(cuò),需要的朋友參考下2017-01-01Java中的字節(jié),字符輸出流與字節(jié)和字符輸入流的簡單理解
這篇文章主要介紹了java 字節(jié)流和字符流的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-07-07設(shè)計(jì)模式系列之組合模式及其在JDK和MyBatis源碼中的運(yùn)用詳解
這篇文章主要介紹了組合模式及其在JDK和MyBatis源碼中的運(yùn)用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09Java實(shí)戰(zhàn)之王者榮耀的英雄是怎么產(chǎn)生的?
這篇文章主要介紹了Java實(shí)戰(zhàn)之王者榮耀的英雄是怎么產(chǎn)生的?文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類
在日常的開發(fā)工作當(dāng)中,我們經(jīng)常需要用到日期相關(guān)的類,下面這篇文章主要給大家介紹了關(guān)于JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09SpringBoot如何監(jiān)控Redis中某個(gè)Key的變化(自定義監(jiān)聽器)
這篇文章主要介紹了SpringBoot如何監(jiān)控Redis中某個(gè)Key的變化(自定義監(jiān)聽器),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09