最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談SpringBoot如何封裝統(tǒng)一響應(yīng)體

 更新時間:2021年05月24日 16:11:23   作者:天貓精靈998  
今天帶各位小伙伴學(xué)習(xí)SpringBoot如何封裝統(tǒng)一響應(yīng)體,文中有非常詳細(xì)的介紹及代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下

一、前言

在上一篇 SpringBoot 參數(shù)校驗 中我們對參數(shù)校驗添加了異常處理,但是還是有不規(guī)范的地方,沒有用統(tǒng)一響應(yīng)體進行返回,在這篇文章中介紹如何封裝統(tǒng)一響應(yīng)體。

關(guān)于統(tǒng)一響應(yīng)體的封裝,沒有一個標(biāo)準(zhǔn)答案,我在各種技術(shù)社區(qū)看了一遍,匯總了一個復(fù)用性比較好的方案。

二、添加結(jié)果類枚舉

在項目目錄下面建一個 responseEntity 的 package,然后在里面建一個 ResultEnum 枚舉類,添加如下代碼:

在這里插入圖片描述

這邊介紹一下枚舉類的用法。枚舉類的作用實際上就是定義常量,如果不使用枚舉類,通常采用靜態(tài)常量來表示:

public static final Integer OK_CODE = 200;
public static final String OK_MESSAGE = "成功";
public static final Integer BAD_REQUEST_CODE = 400;
public static final String BAD_REQUEST_MESSAGE = "參數(shù)錯誤";

這樣的話存在一些問題,一是字段表意不明,特別是看別人的代碼時,會很懵逼;第二當(dāng)業(yè)務(wù)規(guī)模增大之后,可能要維護成百上千的靜態(tài)常量,如果都寫在一個文件里面,容易造成命名混淆,閱讀也比較麻煩。

然后使用枚舉類定義常量就比較方便,相當(dāng)于一個接口,使用時只需要封裝內(nèi)部的數(shù)據(jù)類型,并且限定數(shù)據(jù)域。而且對于不同的枚舉變量,可以調(diào)用不同的處理方法(實現(xiàn)枚舉類的抽象方法可以做到這一點)。關(guān)于枚舉類的一些知識點匯總?cè)缦拢?/p>

  • 使用enum定義的枚舉類默認(rèn)繼承了java.lang.Enum,實現(xiàn)了java.lang.Comparable接口,且不能繼承其他類,也不可以被繼承。但枚舉類可以實現(xiàn)一個或多個接口;
  • 枚舉類的所有實例必須放在第一行顯示,不需使用new,不需顯示調(diào)用構(gòu)造方法,每個變量都是public static final修飾的,最終以分號結(jié)束。在之后的反編譯中,我們就可以理解枚舉類其實也是顆語法糖;
  • 枚舉類的構(gòu)造方法是私有的,默認(rèn)的就是 private,所以不用再添加 private;

枚舉類內(nèi)部常用的方法:

  • valueOf() :返回當(dāng)前枚舉類的name屬性,如果沒有,則throw new java.lang.IllegalArgumentException();
  • values() :是編譯器自動生成的方法,Enum中并沒有該方法,返回包括所有枚舉變量的數(shù)組;
  • toString()name() :兩個方法一樣,返回當(dāng)前枚舉類變量的name屬性,如果覺得不夠用,可以覆蓋默認(rèn)的 toString ,結(jié)合 SWITCH CASE 來靈活的實現(xiàn) toString() 方法;
  • ordinal() :枚舉類會給所有的枚舉變量一個默認(rèn)的次序,該次序從0開始,是根據(jù)我們定義的次序來排序的。而ordinal()方法就是獲取這個次序(或者說下標(biāo));
  • compareTo() :比較的是兩個枚舉變量的次序,返回兩個次序相減后的結(jié)果;

定義了枚舉類之后,在類的上面添加 lombok 的 @Getter 注解,給對象的每個屬性添加 getter 方法,方便后面獲取常量。例如要獲取 OK 的狀態(tài)碼,就可以這樣寫:

ResultEnum.OK.getCode()

這邊再解釋下 @Data 、@Getter@Setter 的區(qū)別:

  • @Data:注解在類上;提供類所有屬性的 getter 和 setter 方法,此外還提供了equals、canEqual、hashCode、toString 方
  • @Getter:注解在屬性上:為屬性提供 getter 方法;注解再類上表示當(dāng)前類中所有屬性都生成getter方法
  • @Setter:注解在屬性上:為屬性提供 setter 方法;注解再類上表示當(dāng)前類中所有屬性都生成setter方法

三、添加統(tǒng)一結(jié)果類

還是在 responseEntity 目錄下面,建一個 ServerResponse 類,添加如下代碼:

@Data
public class ServerResponse {
	private Boolean success;
    private Integer code;
    private String message;
    private Object data;

	// 構(gòu)造方法設(shè)為私有
    private ServerResponse() {}

	public static ServerResponse ok(Object params) {
        ServerResponse serverResponse = new ServerResponse();
        serverResponse.setSuccess(ResultEnum.OK.getSuccess());
        serverResponse.setCode(ResultEnum.OK.getCode());
        serverResponse.setMessage(ResultEnum.OK.getMessage()); // 成功展示默認(rèn)提示信息
        serverResponse.setData(params); // 返回傳入的參數(shù)
        return serverResponse;
    }

	public static ServerResponse badRequest(@Nullable String message) {
        ServerResponse serverResponse = new ServerResponse();
        serverResponse.setSuccess(ResultEnum.BAD_REQUEST.getSuccess());
        serverResponse.setCode(ResultEnum.BAD_REQUEST.getCode());
        serverResponse.setMessage(message != null ? message : ResultEnum.BAD_REQUEST.getMessage()); // 校驗失敗傳入指定的提示信息
        serverResponse.setData(null); // 校驗失敗不返回參數(shù)
        return serverResponse;
    }
}

在上面的代碼中,成員變量和構(gòu)造方法都是私有的,只有靜態(tài)方法向外暴露。然后處理成功的方法,message 展示默認(rèn)提示信息,即定義在枚舉類里面的常量,data 是需要傳給前端的 JSON 參數(shù);處理參數(shù)錯誤的方法,message 展示傳進去的錯誤信息,如果傳的是 null ,則展示默認(rèn)提示信息,即定義在枚舉類里面的常量,data 是傳給前端的參數(shù),但是在參數(shù)錯誤的情況下就不需要傳了,因此是 null

這邊有一個問題,暫時不清楚 Java 是否支持函數(shù)參數(shù)可選,本人測試發(fā)現(xiàn)定義函數(shù)的時候有參數(shù),但是調(diào)用的時候不傳,IDE 會給錯誤提示,因此這里通過傳 null 來解決

四、控制層返回

在定義了統(tǒng)一結(jié)果類之后,就可以在接口中使用了。還是用之前那個方法,通過 POST 請求獲取用戶信息,再原封不動返回過去:

@PostMapping("validateUser")
public ServerResponse userValidate(@RequestBody @Validated UserDTO userDTO) {
    return ServerResponse.ok(null);
}

這邊先給參數(shù)傳 null ,不給前端進行返回,看一下響應(yīng)的結(jié)果:

在這里插入圖片描述

然后傳遞參數(shù):

@PostMapping("validateUser")
public ServerResponse userValidate(@RequestBody @Validated UserDTO userDTO) {
    return ServerResponse.ok(userDTO);
}

看一下響應(yīng)的結(jié)果:

在這里插入圖片描述

五、異常處理類使用統(tǒng)一響應(yīng)體

然后我們給異常處理的方法也添加統(tǒng)一響應(yīng)體:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ServerResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        // 注意傳進去的表達式有可能是 null
        // 因此在 ServerResponse 對 message 是否為 null 進行了判斷
        // 如果是 null 就展示默認(rèn)的提示內(nèi)容
        return ServerResponse.badRequest(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }

    // 其他異常處理方法
}

然后我們模擬一下參數(shù)異常的情況:

在這里插入圖片描述

這樣看起來是正常了,但是存在一個問題,后端判斷參數(shù)異常的時候,因為我們捕獲了異常,所以返回給前端的狀態(tài)碼還是 200 ,如何讓狀態(tài)碼改為 400 呢?在 SpringBoot 中指定 HTTP 狀態(tài)碼主要有三種方式:

  • HttpServletResponse
  • @ResponseStatus
  • ResponseEntity

這邊使用第三種方式,具體的用法看一下代碼應(yīng)該就明白了。我們把剛才統(tǒng)一結(jié)果類的方法修改下:

public static ResponseEntity<ServerResponse> badRequest(@Nullable String message) {
	ServerResponse serverResponse = new ServerResponse();
    serverResponse.setSuccess(ResultEnum.BAD_REQUEST.getSuccess());
    serverResponse.setCode(ResultEnum.BAD_REQUEST.getCode());
    serverResponse.setMessage(message != null ? message : ResultEnum.BAD_REQUEST.getMessage()); // 校驗失敗傳入指定的提示信息
    serverResponse.setData(null); // 校驗失敗不返回參數(shù)
    return new ResponseEntity<>(serverResponse, HttpStatus.BAD_REQUEST); // 使用 ResponseEntity 對象設(shè)置響應(yīng)狀態(tài)碼
}

可以看到我們用一個 ResponseEntity 對象包裹了我們封裝的響應(yīng)體,然后返回了這個對象。其中第二個參數(shù)就是狀態(tài)碼,HttpStatus.BAD_REQUEST 就代表 400 。然后我們還要修改下異常處理類的返回類型:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseEntity<ServerResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        return ServerResponse.badRequest(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }

    // 其他異常處理方法
}

再來調(diào)試一下,這下狀態(tài)碼正常了:

在這里插入圖片描述

在統(tǒng)一結(jié)果類中所有的方法都根據(jù)上面的示例進行修改即可,我這邊添加了幾個方法,給各位參考下,具體可以根據(jù)業(yè)務(wù)場景進行添加:

@Data
public class ServerResponse {
    private Boolean success;
    private Integer code;
    private String message;
    private Object data;

    // 構(gòu)造方法設(shè)為私有
    private ServerResponse() {}

    /**
     * 200 請求成功
     * @param params 傳給前端的參數(shù)
     * @return ResponseEntity<ServerResponse>
     */
    public static ResponseEntity<ServerResponse> ok(Object params) {
        ServerResponse serverResponse = new ServerResponse();
        serverResponse.setSuccess(ResultEnum.OK.getSuccess());
        serverResponse.setCode(ResultEnum.OK.getCode());
        serverResponse.setMessage(ResultEnum.OK.getMessage()); // 成功展示默認(rèn)提示信息
        serverResponse.setData(params); // 返回傳入的參數(shù)
        return new ResponseEntity<>(serverResponse, HttpStatus.OK);
    }

    /**
     * 201 創(chuàng)建成功
     * @return ResponseEntity<ServerResponse>
     */
    public static ResponseEntity<ServerResponse> created() {
        ServerResponse serverResponse = new ServerResponse();
        serverResponse.setSuccess(ResultEnum.CREATED.getSuccess());
        serverResponse.setCode(ResultEnum.CREATED.getCode());
        serverResponse.setMessage(ResultEnum.CREATED.getMessage());
//        serverResponse.setData(null);
        return new ResponseEntity<>(serverResponse, HttpStatus.CREATED);
    }

    /**
     * 204 請求成功,沒有響應(yīng)體
     * @return ResponseEntity<ServerResponse>
     */
    public static ResponseEntity<ServerResponse> noContent() {
        return new ResponseEntity<>(null, HttpStatus.NO_CONTENT);
    }

    /**
     * 400 參數(shù)錯誤
     * @param message 自定義錯誤信息
     * @return ResponseEntity<ServerResponse>
     */
    public static ResponseEntity<ServerResponse> badRequest(@Nullable String message) {
        ServerResponse serverResponse = new ServerResponse();
        serverResponse.setSuccess(ResultEnum.BAD_REQUEST.getSuccess());
        serverResponse.setCode(ResultEnum.BAD_REQUEST.getCode());
        serverResponse.setMessage(message != null ? message : ResultEnum.BAD_REQUEST.getMessage()); // 校驗失敗傳入指定的提示信息
//        serverResponse.setData(null); // 校驗失敗不返回參數(shù)
        return new ResponseEntity<>(serverResponse, HttpStatus.BAD_REQUEST); // 使用 ResponseEntity 對象設(shè)置響應(yīng)狀態(tài)碼
    }
}

此外,@ResponseStatus 也是一種設(shè)置狀態(tài)碼常用的方法,只需要在 Controller 方法中加一個注解就可以:

@PostMapping("validateUser")
@ResponseStatus(code=HttpStatus.BAD_REQUEST, reason="參數(shù)異常")
public ServerResponse userValidate(@RequestBody @Validated UserDTO userDTO) {
    return ServerResponse.ok(userDTO);
}

到此這篇關(guān)于淺談SpringBoot如何封裝統(tǒng)一響應(yīng)體的文章就介紹到這了,更多相關(guān)SpringBoot封裝統(tǒng)一響應(yīng)體內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot @Scheduled定時任務(wù)代碼實例解析

    Spring Boot @Scheduled定時任務(wù)代碼實例解析

    這篇文章主要介紹了Spring Boot @Scheduled定時任務(wù)代碼實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • spring mvc中@PathVariable / 帶斜杠方式獲取

    spring mvc中@PathVariable / 帶斜杠方式獲取

    這篇文章主要介紹了spring mvc中@PathVariable / 帶斜杠方式獲取,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • IDEA運行Java項目報錯java: 錯誤: 不支持發(fā)行版本 xx的解決方法

    IDEA運行Java項目報錯java: 錯誤: 不支持發(fā)行版本 xx的解決方法

    這篇文章主要介紹了IDEA運行Java項目報錯java: 錯誤: 不支持發(fā)行版本 xx的解決方法,文中有詳細(xì)的解決方案供大家參考,對大家解決問題有一定的幫助,需要的朋友可以參考下
    2025-04-04
  • 基于Spring的注解@Qualifier小結(jié)

    基于Spring的注解@Qualifier小結(jié)

    這篇文章主要介紹了Spring的注解@Qualifier小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 代碼詳解Java猴子選王問題(約瑟夫環(huán))

    代碼詳解Java猴子選王問題(約瑟夫環(huán))

    本篇文章通過實例給大家分析了java約瑟夫環(huán)這個經(jīng)典內(nèi)容,有興趣的跟著小編一起學(xué)習(xí)下吧。
    2018-02-02
  • Java面試基礎(chǔ)之TCP連接以及其優(yōu)化

    Java面試基礎(chǔ)之TCP連接以及其優(yōu)化

    這篇文章主要給大家介紹了關(guān)于Java面試基礎(chǔ)之TCP連接以及其優(yōu)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • java設(shè)計模式--橋接模式詳解

    java設(shè)計模式--橋接模式詳解

    這篇文章主要為大家詳細(xì)介紹了java設(shè)計模式之橋接模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助
    2021-07-07
  • Spring中的Sentinel規(guī)則持久化解析

    Spring中的Sentinel規(guī)則持久化解析

    這篇文章主要介紹了Spring中的Sentinel規(guī)則持久化解析,具體內(nèi)容包括,Sentinel規(guī)則推送三種模式介紹,原始模式,拉模式,推模式,并對基于Nacos配置中心控制臺實現(xiàn)推送進行詳盡介紹,需要的朋友可以參考下
    2023-09-09
  • 一個注解搞定Spring Security基于Oauth2的SSO單點登錄功能

    一個注解搞定Spring Security基于Oauth2的SSO單點登錄功能

    本文主要介紹 同域 和 跨域 兩種不同場景單點登錄的實現(xiàn)原理,并使用 Spring Security 來實現(xiàn)一個最簡單的跨域 SSO客戶端。對Spring Security基于Oauth2的SSO單點登錄功能感興趣的朋友一起看看吧
    2021-09-09
  • Java中異常Exception和捕獲以及自定義異常詳解

    Java中異常Exception和捕獲以及自定義異常詳解

    在工作過程中,我們常常需要在合適的地方拋出合適的異常,除了java自帶的一些異常,我們可以在項目中定制自己的異常,并且全局捕獲它,下面這篇文章主要給大家介紹了關(guān)于Java中異常Exception和捕獲以及自定義異常的相關(guān)資料,需要的朋友可以參考下
    2023-05-05

最新評論

龙山县| 巴青县| 龙门县| 蓬溪县| 永仁县| 昌邑市| 裕民县| 武胜县| 法库县| 社旗县| 静安区| 泸水县| 琼结县| 闻喜县| 绍兴县| 乐安县| 浠水县| 惠安县| 乐业县| 黔西县| 精河县| 全州县| 沁阳市| 石门县| 梅州市| 化州市| 西藏| 伽师县| 黔西县| 财经| 武陟县| 永兴县| 吉林市| 南雄市| 尤溪县| 都江堰市| 商河县| 凤台县| 革吉县| 河西区| 宣化县|