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

Spring?Boot數(shù)據(jù)響應(yīng)問題實(shí)例詳解

 更新時間:2022年03月14日 14:10:44   作者:花粥之間  
這篇文章主要給大家介紹了關(guān)于Spring?Boot數(shù)據(jù)響應(yīng)問題的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

前言

響應(yīng)頁面指的是我們?nèi)绾伟l(fā)送一個請求,跳轉(zhuǎn)到指定頁面。將會在后面的視圖解析中說明。 響應(yīng)頁面常見于開發(fā)單體應(yīng)用。 響應(yīng)數(shù)據(jù)常見于開發(fā)前后端分離的應(yīng)用。后端代碼主要用來接收請求。前端頁面給我們發(fā)送過來請求,給前端響應(yīng)json數(shù)據(jù)?;蛘呓o前端響應(yīng)xml、圖片、音視頻數(shù)據(jù)。

在前后端分離開發(fā)過程中,后端一般會將數(shù)據(jù)集封裝成一個JSON對象響應(yīng)給前端 ,一般只需要標(biāo)準(zhǔn)ResponseBody即可給前端返回?cái)?shù)據(jù)

1、響應(yīng)Json數(shù)據(jù):Jackson.jar+@ResponseBody

假設(shè)給前端自動返回json數(shù)據(jù),需要引入相關(guān)的依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- web場景自動引入了json場景 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
</dependency>

控制層代碼如下:引入了依賴后,給方法上標(biāo)注@ResponseBody,就可以給前端自動返回JSON數(shù)據(jù)。

@Controller
public class ResponseTestController {
    @ResponseBody //原理就是利用返回值處理器里面消息轉(zhuǎn)換器進(jìn)行處理
    @GetMapping("/test/person")
    public Person getPerson(){
        Person person = new Person();
        person.setAge(28);
        person.setBirth(new Date());
        person.setUserName("zhangsan");
        return person;
    }

}

測試:

2、原理解析

  • 返回值處理器判斷是否支持這種類型返回值supportsReturnType
  • 返回值處理器調(diào)用handleReturnValue進(jìn)行處理
  • RequestResponseBodyMethodProcessor可以處理返回值標(biāo)了@ResponseBody注解的。
    • 利用MessageConverters進(jìn)行處理將數(shù)據(jù)寫為json
      • 內(nèi)容協(xié)商(瀏覽器默認(rèn)會以請求頭的方式告訴服務(wù)器他能接受什么樣的內(nèi)容類型)
      • 服務(wù)器最終根據(jù)自己自身的能力,決定服務(wù)器能生產(chǎn)出什么樣內(nèi)容類型的數(shù)據(jù),
      • SpringMVC會挨個遍歷所有容器底層的HttpMessageConverter,看誰能處理?(也就是把對象轉(zhuǎn)換成為json數(shù)據(jù))
        • 得到MappingJackson2HttpMessageConverter消息轉(zhuǎn)換器可以將對象寫為json
        • 利用MappingJackson2HttpMessageConverter將對象轉(zhuǎn)為json再寫出去。

SpringMVC到底支持哪些返回值

  • ModelAndView //包含數(shù)據(jù)和頁面
  • Model
  • View
  • ResponseEntity
  • ResponseBodyEmitter
  • StreamingResponseBody
  • HttpEntity
  • HttpHeaders
  • Callable //異步
  • DeferredResult
  • ListenableFuture
  • CompletionStage
  • WebAsyncTask
  • 有 @ModelAttribute 且為對象類型的
  • @ResponseBody 注解 ---> RequestResponseBodyMethodProcessor;處理器//即在方法上或者類上是否標(biāo)注@ResponseBody

HTTPMessageConverter原理

MessageConverter規(guī)范

HttpMessageConverter:看是否支持將 此 Class類型的對象,轉(zhuǎn)為MediaType類型的數(shù)據(jù)。 例子:CanWrite將Person對象轉(zhuǎn)為JSON。canRead或者 JSON轉(zhuǎn)為Person

默認(rèn)的MessageConverter

  • 0 - 只支持Byte類型的
  • 1 - String
  • 2 - String
  • 3 - Resource
  • 4 - ResourceRegion
  • 5 - DOMSource.class \ SAXSource.class) \ StAXSource.class \StreamSource.class \Source.class
  • 6 - MultiValueMap
  • 7 - true //支持將任意對象轉(zhuǎn)為指定的,不管是什么都支持
  • 8 - true
  • 9 - 支持注解方式xml處理的。

最終 MappingJackson2HttpMessageConverter 把對象轉(zhuǎn)為JSON(利用底層的jackson的objectMapper轉(zhuǎn)換的)

3、內(nèi)容協(xié)商

3.1、概述

根據(jù)客戶端接收能力不同【有的只接收xml,有的只接收json】,返回不同媒體類型的數(shù)據(jù)。比如返回xml數(shù)據(jù)給前

引入支持XML依賴:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

重新編譯該項(xiàng)目運(yùn)行 ,返回了xml數(shù)據(jù)

3.2、postman分別測試返回json和xml

在上面的測試中,此時如果我用postman發(fā)送相同的請求,則得到的是json數(shù)據(jù),為啥同樣的請求,方式不一樣,返回的數(shù)據(jù)不一樣呢。原因就是請求頭中規(guī)定的數(shù)據(jù)響應(yīng)先后順序

查看請求頭

在這里插入圖片描述

內(nèi)容協(xié)商Accept中,瀏覽器具備什么類型數(shù)據(jù)的接收能力,可以看到xml數(shù)據(jù)是優(yōu)先被接收的。

可用Postman軟件分別測試返回json和xml:只需要改變請求頭中Accept字段(application/json、application/xml)。Http協(xié)議中規(guī)定的,告訴服務(wù)器本客戶端可以接收的數(shù)據(jù)類型。

3.3、開啟瀏覽器參數(shù)方式內(nèi)容協(xié)商功能

為了方便內(nèi)容協(xié)商,開啟基于請求參數(shù)的內(nèi)容協(xié)商功能。

spring:
    contentnegotiation:
      favor-parameter: true  #開啟請求參數(shù)內(nèi)容協(xié)商模式

發(fā)請求:

  • json類型: http://localhost:8080/test/person?format=json
  • xml類型:http://localhost:8080/test/person?format=xml

確定客戶端接收什么樣的內(nèi)容類型;

1、Parameter策略優(yōu)先確定是要返回json數(shù)據(jù)(獲取請求頭中的format的值) 2、最終進(jìn)行內(nèi)容協(xié)商返回給客戶端json即可。

4、內(nèi)容協(xié)商原理

  • 判斷當(dāng)前響應(yīng)頭中是否已經(jīng)有確定的媒體類型。MediaType
  • 獲取客戶端(PostMan、瀏覽器)支持接收的內(nèi)容類型。(獲取客戶端Accept請求頭字段)【application/xml】
  • contentNegotiationManager 內(nèi)容協(xié)商管理器 默認(rèn)使用基于請求頭的策略
  • HeaderContentNegotiationStrategy 確定客戶端可以接收的內(nèi)容類型
  • 遍歷循環(huán)所有當(dāng)前系統(tǒng)的 MessageConverter,看誰支持操作這個對象(Person)
  • 找到支持操作Person的converter,把converter支持的媒體類型統(tǒng)計(jì)出來。
  • 客戶端需要【application/xml】。服務(wù)端能力【10種、json、xml】
  • 進(jìn)行內(nèi)容協(xié)商的最佳匹配媒體類型
  • 用 支持 將對象轉(zhuǎn)為 最佳匹配媒體類型 的converter。調(diào)用它進(jìn)行轉(zhuǎn)化 。

導(dǎo)入了jackson處理xml的包,xml的converter就會自動進(jìn)來

WebMvcConfigurationSupport
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);

if (jackson2XmlPresent) {
                    Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
                    if (this.applicationContext != null) {
                            builder.applicationContext(this.applicationContext);
                    }
                    messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
            }

5、自定義消息轉(zhuǎn)換器MessageConverter

5.1、概述

實(shí)現(xiàn)多協(xié)議數(shù)據(jù)兼容。json、xml、x-guigu

  • @ResponseBody 響應(yīng)數(shù)據(jù)出去 調(diào)用 RequestResponseBodyMethodProcessor 處理
  • Processor 處理方法返回值。通過 MessageConverter 處理
  • 所有 MessageConverter 合起來可以支持各種媒體類型數(shù)據(jù)的操作(讀、寫)
  • 內(nèi)容協(xié)商找到最終的 messageConverter;

要自定義SpringMVC的什么功能,即通過一個入口給容器中添加一個 WebMvcConfigurer

假設(shè)你想基于自定義請求參數(shù)的自定義內(nèi)容協(xié)商功能。換句話,在地址欄輸入http://localhost:8080/test/person?format=gg返回?cái)?shù)據(jù),跟http://localhost:8080/test/person且請求頭參數(shù)`Accept:application/x-guigu`的返回自定義協(xié)議數(shù)據(jù)的一致。

演示

通過上文分析,我們只需要實(shí)現(xiàn)WebMvcConfigurer接口,并實(shí)現(xiàn)了configureMessageConverters方法,就可以達(dá)到自定義消息轉(zhuǎn)換器的目的。例如,我不想用jackson了,想用fastjson的消息轉(zhuǎn)換器,我們可以添加fastjson相關(guān)的MessageConverter就可以了

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.TEXT_HTML);
        fastMediaTypes.add(MediaType.APPLICATION_JSON);
        fastConverter.setSupportedMediaTypes(fastMediaTypes);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullStringAsEmpty,
            SerializerFeature.WriteNullListAsEmpty,
            SerializerFeature.WriteDateUseDateFormat);
        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        fastJsonConfig.setSerializeConfig(serializeConfig);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);
    }
}

測試

@Data
public class Person {
    private String userName;
    private Integer age;
    //使用fastjson的注解進(jìn)行轉(zhuǎn)換
    @JSONField(format = "yyyy-MM-dd")
    private Date birth;
    private Pet pet;
}

5.2、自定義的Converter

除此之外,這些都是默認(rèn)的,我們可以進(jìn)行擴(kuò)展,如下實(shí)現(xiàn)自定義的設(shè)置轉(zhuǎn)化,如下,利用這個代碼:

@Bean
public WebMvcConfigurer webMvcConfigurer(){
    return new WebMvcConfigurer() {

        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

        }
    }
}

測試

@Configuration(proxyBeanMethods = false)
public class WebConfig {
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {

            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new GuiguMessageConverter());
            }
        }
    }
}
/**
 * 自定義的Converter
 */
public class GuiguMessageConverter implements HttpMessageConverter<Person> {

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return false;
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }

    /**
     * 服務(wù)器要統(tǒng)計(jì)所有MessageConverter都能寫出哪些內(nèi)容類型
     *
     * application/x-guigu
     * @return
     */
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-guigu");
    }

    @Override
    public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    @Override
    public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        //自定義協(xié)議數(shù)據(jù)的寫出
        String data = person.getUserName()+";"+person.getAge()+";"+person.getBirth();


        //寫出去
        OutputStream body = outputMessage.getBody();
        body.write(data.getBytes());
    }
}

測試:

import java.util.Date;

@Controller
public class ResponseTestController {

    /**
     * 1、瀏覽器發(fā)請求直接返回 xml    [application/xml]        jacksonXmlConverter
     * 2、如果是ajax請求 返回 json   [application/json]      jacksonJsonConverter
     * 3、如果硅谷app發(fā)請求,返回自定義協(xié)議數(shù)據(jù)  [appliaction/x-guigu]   xxxxConverter
     *          屬性值1;屬性值2;
     *
     * 步驟:
     * 1、添加自定義的MessageConverter進(jìn)系統(tǒng)底層
     * 2、系統(tǒng)底層就會統(tǒng)計(jì)出所有MessageConverter能操作哪些類型
     * 3、客戶端內(nèi)容協(xié)商 [guigu--->guigu]
     *
     * 作業(yè):如何以參數(shù)的方式進(jìn)行內(nèi)容協(xié)商
     * @return
     */
    @ResponseBody  //利用返回值處理器里面的消息轉(zhuǎn)換器進(jìn)行處理
    @GetMapping(value = "/test/person")
    public Person getPerson(){
        Person person = new Person();
        person.setAge(28);
        person.setBirth(new Date());
        person.setUserName("zhangsan");
        return person;
    }
}

日后開發(fā)要注意,有可能我們添加的自定義的功能會覆蓋默認(rèn)很多功能,導(dǎo)致一些默認(rèn)的功能失效。

總結(jié)

到此這篇關(guān)于Spring Boot數(shù)據(jù)響應(yīng)問題的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)響應(yīng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven解決jar包版本沖突的4種方法詳解

    Maven解決jar包版本沖突的4種方法詳解

    這篇文章主要給大家介紹了關(guān)于Maven解決jar包版本沖突的4種方法代碼,maven工程要導(dǎo)入jar包的坐標(biāo),就必須要考慮解決jar包沖突,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Java文件斷點(diǎn)續(xù)傳實(shí)現(xiàn)原理解析

    Java文件斷點(diǎn)續(xù)傳實(shí)現(xiàn)原理解析

    這篇文章主要介紹了Java文件斷點(diǎn)續(xù)傳實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • 基于HashMap遍歷和使用方法(詳解)

    基于HashMap遍歷和使用方法(詳解)

    下面小編就為大家?guī)硪黄贖ashMap遍歷和使用方法(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • SpringBoot Session接口驗(yàn)證實(shí)現(xiàn)流程詳解

    SpringBoot Session接口驗(yàn)證實(shí)現(xiàn)流程詳解

    這篇文章主要介紹了SpringBoot+Session實(shí)現(xiàn)接口驗(yàn)證(過濾器+攔截器)文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-09-09
  • springboot整合minio實(shí)現(xiàn)文件上傳與下載且支持鏈接永久訪問

    springboot整合minio實(shí)現(xiàn)文件上傳與下載且支持鏈接永久訪問

    本文主要介紹了springboot整合minio實(shí)現(xiàn)文件上傳與下載且支持鏈接永久訪問,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 如何用Maven開發(fā)Spring?Boot項(xiàng)目詳解

    如何用Maven開發(fā)Spring?Boot項(xiàng)目詳解

    SpringBoot是一個集成Spring框架優(yōu)點(diǎn)的開源后臺開發(fā)框架,自動化配置和內(nèi)嵌容器等特性減少了配置工作量,使得開發(fā)者可以更加專注于業(yè)務(wù)邏輯,這篇文章主要介紹了如何用Maven開發(fā)Spring?Boot項(xiàng)目,需要的朋友可以參考下
    2024-09-09
  • idea中引入了gb2312編碼的文件的解決方法

    idea中引入了gb2312編碼的文件的解決方法

    這篇文章主要介紹了idea中引入了gb2312編碼的文件的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 利用HttpUrlConnection 上傳 接收文件的實(shí)現(xiàn)方法

    利用HttpUrlConnection 上傳 接收文件的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄肏ttpUrlConnection 上傳 接收文件的實(shí)現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • HTTP基本認(rèn)證(Basic Authentication)的JAVA實(shí)例代碼

    HTTP基本認(rèn)證(Basic Authentication)的JAVA實(shí)例代碼

    下面小編就為大家?guī)硪黄狧TTP基本認(rèn)證(Basic Authentication)的JAVA實(shí)例代碼。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • SpringBoot 監(jiān)聽Redis鍵過期事件(過期監(jiān)聽)

    SpringBoot 監(jiān)聽Redis鍵過期事件(過期監(jiān)聽)

    Redis鍵過期事件是SpringBoot中常用的緩存失效通知方式,通過配置可以監(jiān)聽特定鍵的過期事件,具有一定的參考價值,感興趣的可以了解一下
    2024-12-12

最新評論

泽州县| 边坝县| 云梦县| 南昌市| 河南省| 两当县| 如东县| 长泰县| 大丰市| 诸城市| 丹凤县| 海晏县| 读书| 淮滨县| 贡山| 宁晋县| 龙州县| 沂源县| 封丘县| 施甸县| 临潭县| 荆州市| 西昌市| 沿河| 岐山县| 思南县| 沁源县| 治多县| 穆棱市| 大埔县| 周口市| 永平县| 胶州市| 射阳县| 博湖县| 平山县| 巴林左旗| 静宁县| 都昌县| 河池市| 利津县|