深入了解SpringBoot中的統(tǒng)一返回和統(tǒng)一異常處理
上篇文章我們學(xué)習(xí)了基于 Token
認證的登錄功能實現(xiàn),分別使用了過濾器和攔截器去實現(xiàn)登錄功能,這篇文章我們來學(xué)習(xí)項目中常用的統(tǒng)一返回結(jié)果和統(tǒng)一異常處理。
一、統(tǒng)一返回結(jié)果
前后端分離時代,如果沒有一個統(tǒng)一的數(shù)據(jù)返回格式,前后端調(diào)試時,前端開發(fā)人員會罵娘的,同時約定相同的返回接口數(shù)據(jù)也有助于高效的工作。
通常統(tǒng)一返回的格式包含三部分:
code
:狀態(tài)碼,一般200
表示正常message
:狀態(tài)碼對應(yīng)的描述。data
:返回的數(shù)據(jù)
1.1、統(tǒng)一返回對象
新建一個 SpringBoot
項目定義通用的響應(yīng)對象
package com.laoxiang.utils; import com.fasterxml.jackson.annotation.JsonInclude; import java.io.Serializable; /** * @author db * @version 1.0 * @description ResponseResult * @since 2023/7/12 */ @JsonInclude(JsonInclude.Include.NON_NULL) public class ResponseResult<T> implements Serializable { private static final long serialVersionUID = 2233637474601103587L; // 接口響應(yīng)狀態(tài)碼 private Integer code; // 接口響應(yīng)信息 private String msg; // 接口響應(yīng)的數(shù)據(jù) 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; } }
1.2、系統(tǒng)常量
上面代碼中提到了常量 AppHttpCodeEnum
,定義自己的應(yīng)用程序特定狀態(tài)碼,來表示具體的情況。通過定義的狀態(tài)碼就可以知道具體代表什么意思。
package com.laoxiang.utils; /** * @author db * @version 1.0 * @description AppHttpCodeEnum * @since 2023/7/12 */ public enum AppHttpCodeEnum { // 成功 SUCCESS(200,"操作成功"), // 失敗 ERROR(500,"操作失敗"), 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; } }
1.3、web 層統(tǒng)一響應(yīng)結(jié)果
下面的例子,可以看到在實際項目中接口返回值。
二、統(tǒng)一異常處理
程序開發(fā)中不可避免的會遇到異常現(xiàn)象,如果不進行處理,遇到異常時,開發(fā)人員不能清晰地處理問題,或者使用 try{...}catch{...}
代碼塊進行處理,但是滿屏的 try{...}catch{...}
代碼塊造成代碼過于臃腫。
有沒有更好的處理方式呢?全局統(tǒng)一異常處理應(yīng)運而生。@ControllerAdvice
注解搭配 @ExceptionHandler
進行全局統(tǒng)一異常處理。
2.1、@ControllerAdvice注解
@ControllerAdvice
注解:用于聲明一個全局控制器 Advice
,相當(dāng)于把 @ExceptionHandler
、@InitBinder
和 @ModelAttribute
注解的方法集中到一個地方。放在特定類上,被認為是全局異常處理器。
2.2、ExceptionHandler 注解
用于定義異常處理方法,處理特定類型的異常。放在全局異常處理器類中的具體方法上。 通過這兩個注解的配合,可以實現(xiàn)全局的異常處理。當(dāng)控制器中拋出異常時,SpringBoot
會自動調(diào)用匹配的 @ExceptionHandler
方法來處理異常,并返回定義的響應(yīng)。
步驟如下:
- 新建一個統(tǒng)一異常處理類
- 類上標(biāo)注
@RestControllerAdvice
注解 - 在方法上標(biāo)注
@ExceptionHandler
注解,并且指定需要捕獲的異常,可以同時捕獲多個。
新建 exception
包,在包下新建 GlobalExceptionHandler
類。代碼如下:
package com.duan.execption; import com.duan.pojo.AppHttpCodeEnum; import com.duan.pojo.ResponseResult; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; /** * @author db * @version 1.0 * @description GlobalExceptionHandler * @since 2023/7/23 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { // 全局異常 @ExceptionHandler(Exception.class) public ResponseResult exceptionHandler(Exception e){ //打印異常信息 log.error("出現(xiàn)了異常! {}",e); //從異常對象中獲取提示信息封裝返回 return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR.getCode(),e.getMessage()); } // 自定義異常 @ExceptionHandler(LxAdminException.class) public ResponseResult LxAdminExceptionHandler(LxAdminException e){ //打印異常信息 log.error("出現(xiàn)了異常! {}",e); //從異常對象中獲取提示信息封裝返回 return ResponseResult.errorResult(e.getCode(),e.getMsg()); } }
在exception
包下新建自定義異常處理類 LxAdminException
package com.duan.execption; import com.duan.pojo.AppHttpCodeEnum; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author db * @version 1.0 * @description LxAdminException 自定義異常 * @since 2023/7/23 */ @Data @AllArgsConstructor @NoArgsConstructor public class LxAdminException extends RuntimeException{ private int code; private String msg; public LxAdminException(AppHttpCodeEnum httpCodeEnum) { super(httpCodeEnum.getMsg()); this.code = httpCodeEnum.getCode(); this.msg = httpCodeEnum.getMsg(); } }
2.3、統(tǒng)一異常處理使用
在業(yè)務(wù)開發(fā)中,可以在 service
層處理業(yè)務(wù)時,可以手動拋出異常,由全局異常處理器處理進行統(tǒng)一處理。
package com.duan.controller; import com.duan.execption.LxAdminException; import com.duan.pojo.AppHttpCodeEnum; import com.duan.pojo.ResponseResult; import com.duan.pojo.User; import com.duan.utils.JWTUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.UUID; /** * @author db * @version 1.0 * @description LoginController * @since 2023/12/19 */ @RestController @Slf4j public class LoginController { @PostMapping("/login") public ResponseResult login(@RequestBody User user){ log.info("這是正常日志"); if(!"admin".equals(user.getUsername()) && !"123456".equals(user.getPassword())){ throw new LxAdminException(AppHttpCodeEnum.LOGIN_ERROR); }else{ HashMap<String, Object> map = new HashMap<>(); map.put("id", UUID.randomUUID().toString()); // 生成token String token = JWTUtils.generateJwt(map); return ResponseResult.okResult(token); } } }
當(dāng)我們請求接口時,假如用戶名稱或者密碼錯誤,接口就會響應(yīng):
{ "code": 505, "msg": "用戶名或密碼錯誤", "data": null }
實際開發(fā)中還有許多的異常需要捕獲,比如 Token
失效、過期等異常, 如果整合了其他的框架,還要注意這些框架拋出的異常,比如Spring Security
等框架。
代碼地址:https://gitee.com/duan138/practice-code/tree/dev/resultException
三、總結(jié)
在 SpringBoot
項目中,統(tǒng)一返回和統(tǒng)一異常處理是非常常用的一環(huán),它們能提高應(yīng)用的可讀性和可維護性,統(tǒng)一返回有助于保持代碼一致性和規(guī)范性,在前后端聯(lián)調(diào)時更加方便,統(tǒng)一異常處理,減少了代碼冗余,對異常處理更加易于管理。
以上就是深入了解SpringBoot中的統(tǒng)一返回和統(tǒng)一異常處理的詳細內(nèi)容,更多關(guān)于SpringBoot統(tǒng)一返回和統(tǒng)一異常處理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JAVA實現(xiàn) springMVC方式的微信接入、實現(xiàn)消息自動回復(fù)實例
本篇文章主要介紹了JAVA實現(xiàn) springMVC方式的微信接入、實現(xiàn)消息自動回復(fù),這里整理了詳細的代碼,有需要的小伙伴可以參考下。2016-12-12并行Stream與Spring事務(wù)相遇會發(fā)生什么?
這篇文章主要介紹了并行Stream與Spring事務(wù)相遇會發(fā)生什么?文章主要解決實戰(zhàn)中的Bug及解決方案和技術(shù)延伸,具有一定的參考價值,需要的小伙伴可以參考一下2022-05-05java發(fā)送heartbeat心跳包(byte轉(zhuǎn)16進制)
這篇文章主要介紹了java發(fā)送heartbeat心跳包(byte轉(zhuǎn)16進制),需要的朋友可以參考下2014-05-05簡單了解JAVA內(nèi)存泄漏和溢出區(qū)別及聯(lián)系
這篇文章主要介紹了簡單了解JAVA內(nèi)存泄漏和溢出區(qū)別及聯(lián)系,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03