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

Spring Boot統(tǒng)一返回體的踩坑記錄

 更新時(shí)間:2021年05月10日 14:13:05   作者:碼農(nóng)小胖哥  
這篇文章主要給大家介紹了關(guān)于Spring Boot統(tǒng)一返回體踩坑的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

在Spring Boot項(xiàng)目中我們可以通過(guò)RestControllerAdvice配合實(shí)現(xiàn)ResponseBodyAdvice<T>接口來(lái)保證Spring MVC接口具有統(tǒng)一的返回格式,以保證前端同學(xué)能夠封裝統(tǒng)一的數(shù)據(jù)接收工具。但是很多網(wǎng)上的文章并沒有對(duì)實(shí)際開發(fā)中的細(xì)節(jié)作出更多的講解。今天胖哥就來(lái)分享一下我的采坑經(jīng)歷,也算作一個(gè)總結(jié)。

控制作用范圍

我記得在前面關(guān)于Swagger3的文章中提過(guò),如果我們不指定范圍將導(dǎo)致Swagger無(wú)法識(shí)別接口的元信息。因此如果你使用了Swagger必須指定其范圍,這里你可以通過(guò)指定掃描包來(lái)指定其作用域:

@RestControllerAdvice("cn.felord.controller")

如果你的Spring MVC控制器有統(tǒng)一的父類控制器的話,

@RestController
@RequestMapping("/foo")
public class FooController extends BaseController {
 //todo 省略
}    

也可以這樣:

@RestControllerAdvice(assignableTypes = BaseController.class)

白名單

有些接口可能根據(jù)業(yè)務(wù)需要或者協(xié)議需要不能使用統(tǒng)一返回體,例如支付的通知應(yīng)答。這就需要一個(gè)類似白名單的機(jī)制來(lái)繞過(guò)統(tǒng)一返回體控制器通知類。我們可以借助于ResponseBodyAdvice<T>的下列方法實(shí)現(xiàn):

boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);

這個(gè)方法如果返回false就表示不執(zhí)行統(tǒng)一返回體的封裝邏輯。這里我推薦注解實(shí)現(xiàn)。定義一個(gè)標(biāo)記注解,可以定義在類上或者方法上:

@Documented
@Inherited
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreRestBody {
}

然后上面的supports方法這樣實(shí)現(xiàn):

@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    return !returnType.hasMethodAnnotation(IgnoreRestBody.class);
}

如果某個(gè)Controller下所有的方法都繞過(guò),就把這個(gè)注解標(biāo)記在控制器類上;如果只想忽略某個(gè)方法上就把它標(biāo)記在該方法上即可。

返回獨(dú)立字符串的問(wèn)題

有些接口我們會(huì)返回一個(gè)字符串:

@GetMapping("/get")
public String getStr(){
    //返回了一個(gè)字符串
    return "felord.cn";
}

我們希望這個(gè)字符串被統(tǒng)一返回體處理,類似這樣:

{
    code: 200,
    data: "felord.cn",
    msg: "返回成字符串",
}

但是你會(huì)發(fā)現(xiàn)并沒有達(dá)到期望的效果,會(huì)拋出類型轉(zhuǎn)換異常。這是因?yàn)楫?dāng)我們的Spring MVC接口返回?cái)?shù)據(jù)時(shí),會(huì)根據(jù)Content-Type來(lái)選擇一個(gè)HttpMessageConverter來(lái)處理,而字符串在不聲明Content-Type的情況下優(yōu)先使用StringHttpMessageConverter ,就導(dǎo)致了轉(zhuǎn)換異常,需要設(shè)定成MappingJackson2HttpMessageConverter用Jackson來(lái)處理,Spring MVC的對(duì)應(yīng)配置如下:

@Configuration(proxyBeanMethods = false)
public class SpringMvcConfiguration implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 解決 String 統(tǒng)一封裝RestBody的問(wèn)題
        converters.add(0, new MappingJackson2HttpMessageConverter());
    }
}

嗯,這樣就起效了!你以為這樣就完了?你會(huì)發(fā)現(xiàn)你的JSON序列化不按照你設(shè)置的策略執(zhí)行了。因?yàn)槟鉵ew了一個(gè)而不是采用系統(tǒng)初始化的那個(gè)。解決方法為,將Spring IoC中的ObjectMapper注入到MappingJackson2HttpMessageConverter中去?;蛘吣闶褂肈ebug調(diào)試出系統(tǒng)默認(rèn)的MappingJackson2HttpMessageConverter的位置,比如我的索引為7,就可以這樣配置:

@Configuration(proxyBeanMethods = false)
public class SpringMvcConfiguration implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 解決 String 統(tǒng)一封裝RestBody的問(wèn)題
        HttpMessageConverter<?> httpMessageConverter = converters.get(7);
        if (!(httpMessageConverter instanceof MappingJackson2HttpMessageConverter)) {
            // 確保正確,如果有改動(dòng)就重新debug
            throw new RuntimeException("MappingJackson2HttpMessageConverter is not here");
        }
        converters.add(0, httpMessageConverter);
    }
}

Data的類型問(wèn)題

曾經(jīng)一個(gè)安卓開發(fā)同學(xué)說(shuō),你這統(tǒng)一結(jié)構(gòu)中的data如果是數(shù)組:

{
    code: 200,
    data: ['a','b'],
    msg: "返回成字符串",
}

后續(xù)如果data添加其它與數(shù)組沒有關(guān)系的屬性就不兼容了,你應(yīng)該保證這個(gè)data是個(gè)Map。是的,這也是問(wèn)題,實(shí)際中發(fā)現(xiàn)不僅僅是數(shù)組,如果是int、long等原始類型或者String類型都面臨這種情況,需要加一個(gè)額外的判斷body是不是可能改變data類型的類型:

private boolean checkPrimitive(Object body) {
    Class<?> clazz = body.getClass();
    return clazz.isPrimitive()
            || clazz.isArray()
            || Collection.class.isAssignableFrom(clazz)
            || body instanceof Number
            || body instanceof Boolean
            || body instanceof Character
            || body instanceof String;
}

然后我們?cè)赗esponseBodyAdvice<T>實(shí)現(xiàn)中增加一個(gè)判斷:

      // 增強(qiáng)擴(kuò)展性
        if (checkPrimitive(body)) {
            return RestBody.okData(Collections.singletonMap("result", body));
        }

就解決問(wèn)題了。

總結(jié)

今天對(duì)Spring Boot中統(tǒng)一返回體的一些細(xì)節(jié)問(wèn)題進(jìn)行了分享,希望能夠幫助你解決一些實(shí)際開發(fā)中遇到的同樣問(wèn)題。

到此這篇關(guān)于Spring Boot統(tǒng)一返回體踩坑記錄的文章就介紹到這了,更多相關(guān)Spring Boot統(tǒng)一返回體內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring中的@PropertySource注解源碼詳解

    Spring中的@PropertySource注解源碼詳解

    這篇文章主要介紹了Spring中的@PropertySource注解源碼詳解,@PropertySource注解用于指定資源文件讀取的位置,它不僅能讀取properties文件,也能讀取xml文件,并且通過(guò)yaml解析器,配合自定義PropertySourceFactory實(shí)現(xiàn)解析yaml文件,需要的朋友可以參考下
    2023-11-11
  • java并發(fā)之Lock接口的深入講解

    java并發(fā)之Lock接口的深入講解

    從Java 5之后,在java.util.concurrent.locks包下提供了另外一種方式來(lái)實(shí)現(xiàn)同步訪問(wèn).那就是Lock,這篇文章主要給大家介紹了關(guān)于java并發(fā)之Lock接口的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • Java中StringRedisTemplate和RedisTemplate的區(qū)別及使用方法

    Java中StringRedisTemplate和RedisTemplate的區(qū)別及使用方法

    本文主要介紹了Java中StringRedisTemplate和RedisTemplate的區(qū)別及使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識(shí)字的示例代碼

    SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識(shí)字的示例代碼

    圖片中的文字提取已經(jīng)越來(lái)越多地應(yīng)用于數(shù)據(jù)輸入和自動(dòng)化處理過(guò)程,本文主要介紹了SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識(shí)字的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • java根據(jù)模板動(dòng)態(tài)生成PDF實(shí)例

    java根據(jù)模板動(dòng)態(tài)生成PDF實(shí)例

    本篇文章主要介紹了java根據(jù)模板動(dòng)態(tài)生成PDF實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • Java 17 更新后的 strictfp 關(guān)鍵字

    Java 17 更新后的 strictfp 關(guān)鍵字

    strictfp 可能是最沒有存在感的關(guān)鍵字了,很多人寫了多年 Java 甚至都不知道它的存在,strictfp,字面意思就是嚴(yán)格的浮點(diǎn)型。這玩意兒居然還有個(gè)關(guān)鍵字,可見其地位還是很高的。下面文章小編就帶大家詳細(xì)介紹其關(guān)鍵字,需要的朋友可以參考一下
    2021-09-09
  • idea 安裝 Mybatis 開發(fā)幫助插件 MyBatisCodeHelper-Pro 插件破解版的方法

    idea 安裝 Mybatis 開發(fā)幫助插件 MyBatisCodeHelper-Pro 插件破解版的方法

    MyBatisCodeHelper-Pro 插件可以幫助我們快速的開發(fā) mybatis,這篇文章給大家介紹idea 安裝 Mybatis 開發(fā)幫助插件 MyBatisCodeHelper-Pro 插件破解版的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧
    2020-09-09
  • Java Web最近面試題匯總

    Java Web最近面試題匯總

    在本篇文章里小編給大家整理的是一篇關(guān)于Java Web最近面試題匯總內(nèi)容,需要的朋友們可以學(xué)習(xí)下。
    2020-02-02
  • Java之int和string類型轉(zhuǎn)換詳解

    Java之int和string類型轉(zhuǎn)換詳解

    這篇文章主要介紹了Java之int和string類型轉(zhuǎn)換詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • spring-Kafka中的@KafkaListener深入源碼解讀

    spring-Kafka中的@KafkaListener深入源碼解讀

    本文主要通過(guò)深入了解源碼,梳理從spring啟動(dòng)到真正監(jiān)聽kafka消息的這套流程,從spring啟動(dòng)開始處理@KafkaListener,本文結(jié)合實(shí)例流程圖給大家講解的非常詳細(xì),需要的朋友參考下
    2023-02-02

最新評(píng)論