欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實戰(zhàn)之實現(xiàn)結果的優(yōu)雅響應案例詳解

 更新時間:2021年09月03日 11:28:38   作者:沉潛飛動  
這篇文章主要介紹了SpringBoot實戰(zhàn)之實現(xiàn)結果的優(yōu)雅響應案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下

今天說一下 Spring Boot 如何實現(xiàn)優(yōu)雅的數(shù)據(jù)響應:統(tǒng)一的結果響應格式、簡單的數(shù)據(jù)封裝。

前提

無論系統(tǒng)規(guī)模大小,大部分 Spring Boot 項目是提供 Restful + json 接口,供前端或其他服務調(diào)用,格式統(tǒng)一規(guī)范,是程序猿彼此善待彼此的象征,也是減少聯(lián)調(diào)挨罵的基本保障。

通常響應結果中需要包含業(yè)務狀態(tài)碼、響應描述、響應時間戳、響應內(nèi)容,比如:

{
"code": 200,
"desc": "查詢成功",
"timestamp": "2020-08-12 14:37:11",
"data": {
"uid": "1597242780874",
"name": "測試 1"
}
}

對于業(yè)務狀態(tài)碼分為兩個派系:一個是推薦使用 HTTP 響應碼作為接口業(yè)務返回;另一種是 HTTP 響應碼全部返回 200,在響應體中通過單獨的字段表示響應狀態(tài)。兩種方式各有優(yōu)劣,個人推薦使用第二種,因為很多 Web 服務器對 HTTP 狀態(tài)碼有攔截處理功能,而且狀態(tài)碼數(shù)量有限,不夠靈活。比如返回 200 表示接口處理成功且正常響應,現(xiàn)在需要有一個狀態(tài)碼表示接口處理成功且正常響應,但是請求數(shù)據(jù)狀態(tài)不對,可以返回 2001 表示。

自定義響應體

定義一個數(shù)據(jù)響應體是返回統(tǒng)一響應格式的第一步,無論接口正常返回,還是發(fā)生異常,返回給調(diào)用方的結構格式都應該不變。給出一個示例:

@ApiModel
@Data
public class Response<T> {
    @ApiModelProperty(value = "返回碼", example = "200")
    private Integer code;
    @ApiModelProperty(value = "返回碼描述", example = "ok")
    private String desc;
    @ApiModelProperty(value = "響應時間戳", example = "2020-08-12 14:37:11")
    private Date timestamp = new Date();
    @ApiModelProperty(value = "返回結果")
    private T data;
}

這樣,只要在 Controller 的方法返回Response就可以了,接口響應就一致了,但是這樣會形成很多格式固定的代碼模板,比如下面這種寫法:

@RequestMapping("hello1")
public Response<String> hello1() {
    final Response<String> response = new Response<>();
    response.setCode(200);
    response.setDesc("返回成功");
    response.setData("Hello, World!");
    return response;
}

調(diào)用接口響應結果為:

{
"code": 200,
"desc": "返回成功",
"timestamp": "2020-08-12 14:37:11",

     "data": "Hello, World!"

}

這種重復且沒有技術含量的代碼,怎么能配得上程序猿這種優(yōu)(lan)雅(duo)的生物呢?最好能在返回響應結果的前提下,減去那些重復的代碼,比如:

@RequestMapping("hello2")
public String hello2() {
    return "Hello, World!";
}

這就需要借助 Spring 提供的ResponseBodyAdvice來實現(xiàn)了。

全局處理響應數(shù)據(jù)

先上代碼:

/**
 * <br>created at 2020/8/12
 *
 * @author www.howardliu.cn
 * @since 1.0.0
 */
@RestControllerAdvice
public class ResultResponseAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(final MethodParameter returnType, final Class<? extends HttpMessageConverter<?>> converterType) {
        return !returnType.getGenericParameterType().equals(Response.class);// 1
    }

    @Override
    public Object beforeBodyWrite(final Object body, final MethodParameter returnType, final MediaType selectedContentType,
                                  final Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  final ServerHttpRequest request, final ServerHttpResponse response) {
        if (body == null || body instanceof Response) {
            return body;
        }
        final Response<Object> result = new Response<>();
        result.setCode(200);
        result.setDesc("查詢成功");
        result.setData(body);
        if (returnType.getGenericParameterType().equals(String.class)) {// 2
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                return objectMapper.writeValueAsString(result);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("將 Response 對象序列化為 json 字符串時發(fā)生異常", e);
            }
        }
        return result;
    }
}

/**
 * <br>created at 2020/8/12
 *
 * @author www.howardliu.cn
 * @since 1.0.0
 */
@RestController
public class HelloWorldController {
    @RequestMapping("hello2")
    public String hello2() {
        return "Hello, World!";
    }

    @RequestMapping("user1")
    public User user1() {
        User u = new User();
        u.setUid(System.currentTimeMillis() + "");
        u.setName("測試1");
        return u;
    }
}

上面代碼是實現(xiàn)了 Spring ResponseBodyAdvice類的模板方式,按照 Spring 的要求實現(xiàn)就行。只有兩個需要特別注意的地方,也就是代碼中標注 1 和 2 的地方。

首先說 1 這一行,也就是supports方法,這個方法是校驗是否需要調(diào)用beforeBodyWrite方法的前置判斷,返回true則執(zhí)行beforeBodyWrite方法,這里根據(jù) Controller 方法返回類型來判斷是否需要執(zhí)行beforeBodyWrite,也可以一律返回true,在后面判斷是否需要進行類型轉(zhuǎn)換。

然后重點說下 2 這一行,這行是坑,是大坑,如果對 Spring 結構不熟悉的,絕對會在這徘徊許久,不得妙法。

代碼 2 這一行是判斷Controller的方法是否返回的是String類型的結果,如果是,將返回的對象序列化之后返回。

這是因為SpringString類型的響應類型單獨處理了,使用StringHttpMessageConverter類進行數(shù)據(jù)轉(zhuǎn)換。在處理響應結果的時候,會在方法getContentLength中計算響應體大小,其父類方法定義是protected Long getContentLength(T t, @Nullable MediaType contentType),而StringHttpMessageConverter將方法重寫為protected Long getContentLength(String str, @Nullable MediaType contentType),第一個參數(shù)是響應對象,固定寫死是String類型,如果我們強制返回Response對象,就會報ClassCastException。

當然,直接返回String的場景不多,這個坑可能會在某天特殊接口中突然出現(xiàn)。

補充說明

上面只是展示了ResponseBodyAdvice類最簡單的應用,我們還可以實現(xiàn)更多的擴展使用。比如:

  1. 返回請求ID:這個需要與與RequestBodyAdvice聯(lián)動,獲取到請求ID后,在響應是放在響應體中;
  2. 結果數(shù)據(jù)加密:通過ResponseBodyAdvice實現(xiàn)響應數(shù)據(jù)加密,不會侵入業(yè)務代碼,而且可以通過注解方式靈活處理接口的加密等級;
  3. 有選擇的包裝響應體:比如定義注解IgnoreResponseWrap,在不需要包裝響應體的接口上定義,然后在supports方法上判斷方法的注解即可,比如:
@Override
public boolean supports(final MethodParameter returnType, final Class<? extends HttpMessageConverter<?>> converterType) {
    final IgnoreResponseWrap[] declaredAnnotationsByType = returnType.getExecutable().getDeclaredAnnotationsByType(IgnoreResponseWrap.class);
    return !(declaredAnnotationsByType.length > 0 || returnType.getGenericParameterType().equals(Response.class));
}

很多其他玩法就不一一列舉了。

總結

上面說了正常響應的數(shù)據(jù),只做到了一點優(yōu)雅,想要完整,還需要考慮接口異常情況,總不能來個大大的try/catch/finally包住業(yè)務邏輯吧,那也太丑了。后面會再來一篇,重點說說接口如何在出現(xiàn)異常時,也能返回統(tǒng)一的結果響應。

本文只是拋出一塊磚,玉還得自己去找。

推薦閱讀

到此這篇關于SpringBoot實戰(zhàn)之實現(xiàn)結果的優(yōu)雅響應案例詳解的文章就介紹到這了,更多相關SpringBoot實戰(zhàn)之實現(xiàn)結果的優(yōu)雅響應內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java深入探索線程安全和線程通信的特性

    Java深入探索線程安全和線程通信的特性

    這篇文章主要介紹了Java線程安全和線程通信的特性,線程安全是多線程編程時的計算機程序代碼中的一個概念。在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會通過同步機制保證各個線程都可以正常且正確的執(zhí)行,不會出現(xiàn)數(shù)據(jù)污染等意外情況
    2022-05-05
  • springboot集成mybatisPlus+多數(shù)據(jù)源的實現(xiàn)示例

    springboot集成mybatisPlus+多數(shù)據(jù)源的實現(xiàn)示例

    這篇文章主要介紹了springboot集成mybatisPlus+多數(shù)據(jù)源的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • IntelliJ IDEA 熱部署插件JRebel的使用

    IntelliJ IDEA 熱部署插件JRebel的使用

    這篇文章主要介紹了IntelliJ IDEA 熱部署插件JRebel的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • springboot排除某些自動配置的操作方法

    springboot排除某些自動配置的操作方法

    Spring Boot 提供的自動配置非常強大,某些情況下,自動配置的功能可能不符合我們的需求,需要我們自定義配置,這個時候就需要排除/禁用Spring Boot 某些類的自動化配置了,本文給大家介紹springboot排除某些自動配置的方法,感興趣的朋友一起看看吧
    2023-08-08
  • java集成開發(fā)SpringBoot生成接口文檔示例實現(xiàn)

    java集成開發(fā)SpringBoot生成接口文檔示例實現(xiàn)

    這篇文章主要為大家介紹了java集成開發(fā)SpringBoot如何生成接口文檔的示例實現(xiàn)過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-10-10
  • 詳解Java對象的內(nèi)存布局

    詳解Java對象的內(nèi)存布局

    這篇文章主要介紹了Java對象的內(nèi)存布局,對對象內(nèi)存感興趣的同學,一定要仔細研究下
    2021-04-04
  • spring boot openfeign從此和httpClient說再見詳析

    spring boot openfeign從此和httpClient說再見詳析

    這篇文章主要給大家介紹了關于spring boot openfeign從此和httpClient說再見的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧
    2018-06-06
  • SpringBoot多環(huán)境配置方式的新手教程

    SpringBoot多環(huán)境配置方式的新手教程

    我們平時做項目的時候,一般都會分幾套環(huán)境,每一套環(huán)境的配置都是不一樣的,所以這篇文章就來為大家詳細介紹一下SpringBoot多環(huán)境配置方式,希望對大家有所幫助
    2023-11-11
  • Java從內(nèi)存角度帶你理解數(shù)組名實質(zhì)是個地址的論述

    Java從內(nèi)存角度帶你理解數(shù)組名實質(zhì)是個地址的論述

    這篇文章主要介紹了Java如何從內(nèi)存解析的角度理解“數(shù)組名實質(zhì)是一個地址”,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-09-09
  • SpringMVC中文亂碼踩坑記錄

    SpringMVC中文亂碼踩坑記錄

    這篇文章主要介紹了SpringMVC中文亂碼踩坑記錄,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08

最新評論