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

SpringBoot響應(yīng)處理實(shí)現(xiàn)流程詳解

 更新時(shí)間:2022年10月08日 11:25:37   作者:Decade0712  
這篇文章主要介紹了SpringBoot響應(yīng)處理實(shí)現(xiàn)流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧

1、相關(guān)依賴

web項(xiàng)目引入的啟動(dòng)器spring-boot-starter-web中含有

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-json</artifactId>
	<version>2.7.0</version>
	<scope>compile</scope>
</dependency>

這個(gè)依賴下面又有jackson的相關(guān)依賴,用于json的轉(zhuǎn)換

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.13.3</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-jdk8</artifactId>
  <version>2.13.3</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-jsr310</artifactId>
  <version>2.13.3</version>
  <scope>compile</scope>
</dependency>

2、ReturnValueHandlers—返回值處理器

之前我們分析了參數(shù)解析器argumentResolvers的相關(guān)源碼,了解了請(qǐng)求中的參數(shù)是如何找到合適的參數(shù)解析器,并與方法的入?yún)⑦M(jìn)行綁定的,那么問(wèn)題來(lái)了,響應(yīng)值的返回值處理器是如何找到的呢?

要分析源碼,我們還是得進(jìn)入DispatcherServlet這個(gè)類下的doDiapatch()方法

與之前分析參數(shù)解析器一樣的流程,我們跟到了RequestMappingHandlerAdapter這個(gè)類下的invokeHandlerMethod()方法

通過(guò)斷點(diǎn)可以看到我們默認(rèn)支持15種返回值解析器

那么他是怎么從這么多返回值解析器中選出自己支持的那一個(gè)呢?

我們可以發(fā)現(xiàn),這些返回值解析器都是實(shí)現(xiàn)了HandlerMethodReturnValueHandler接口

package org.springframework.web.method.support;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.context.request.NativeWebRequest;
public interface HandlerMethodReturnValueHandler {
    boolean supportsReturnType(MethodParameter returnType);
    void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}

此接口下只有2個(gè)方法,一個(gè)是判斷是否支持此類型返回值,另一個(gè)是處理返回值的方法

是不是和之前的參數(shù)解析器的接口類有異曲同工之妙?

沒(méi)錯(cuò),我們正是使用這兩個(gè)方法來(lái)尋找適合自己的返回值解析器以及處理我們的返回值

跟著斷點(diǎn)一直向下,我們跟到了HandlerMethodReturnValueHandlerComposite類下的handleReturnValue()方法,在這里,我們就找到了對(duì)應(yīng)的解析器并執(zhí)行了相關(guān)方法

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
	// 獲取自己適合的返回值解析器
    HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
    if (handler == null) {
        throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    } else {
    	// 調(diào)用該返回值解析器中的處理返回值的方法
        handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }
}
@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
	// 判斷是否是異步的返回值
    boolean isAsyncValue = this.isAsyncReturnValue(value, returnType);
    Iterator var4 = this.returnValueHandlers.iterator();
    HandlerMethodReturnValueHandler handler;
    // 使用do-while進(jìn)行遍歷,找出支持當(dāng)前返回值類型的解析器
    do {
        do {
            if (!var4.hasNext()) {
                return null;
            }

            handler = (HandlerMethodReturnValueHandler)var4.next();
        } while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler));
    } while(!handler.supportsReturnType(returnType));
    return handler;
}

最終,我們確定使用解析器RequestResponseBodyMethodProcessor可以處理標(biāo)注了@ResponseBody的返回值

3、HttpMessageConvert—消息轉(zhuǎn)換器

除了尋找合適的返回值解析器之外,我們還有一個(gè)問(wèn)題要思考

為什么我們?cè)诳刂破黝惖姆椒ㄉ霞右粋€(gè)@ResponseBody注解就能將響應(yīng)信息轉(zhuǎn)換成json格式呢?

這個(gè)轉(zhuǎn)換是怎樣實(shí)現(xiàn)的呢?

我們接著上面的代碼繼續(xù)往下debug

之前我們已經(jīng)定位到了使用RequestResponseBodyMethodProcessor來(lái)處理@ResponseBody的返回值,所以我們繼續(xù)深入到這個(gè)類下的handleReturnValue()

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
	mavContainer.setRequestHandled(true);
	// 創(chuàng)建輸入和輸出信息
	ServletServerHttpRequest inputMessage = this.createInputMessage(webRequest);
	ServletServerHttpResponse outputMessage = this.createOutputMessage(webRequest);
	// 使用消息轉(zhuǎn)換器進(jìn)行寫(xiě)出操作
	this.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

然后我們來(lái)分析解析器父類AbstractMessageConverterMethodProcessor下的writeWithMessageConverters()方法

首先我們了解一個(gè)概念:什么是內(nèi)容協(xié)商?

瀏覽器默認(rèn)會(huì)以請(qǐng)求頭的方式告訴服務(wù)器他能接受什么樣的內(nèi)容類型,這里的q代表優(yōu)先級(jí)

然后服務(wù)器最終根據(jù)自己自身的能力,決定服務(wù)器能生產(chǎn)出什么樣內(nèi)容類型的數(shù)據(jù)

所以在writeWithMessageConverters()方法中我們獲取到瀏覽器能接受什么內(nèi)容

以及服務(wù)器能產(chǎn)生什么內(nèi)容

然后我們經(jīng)過(guò)協(xié)商,決定返回application/json格式的數(shù)據(jù)

重點(diǎn)來(lái)了:這里有一系列的消息轉(zhuǎn)換器,我們到底使用哪個(gè)呢?

隨便點(diǎn)進(jìn)一個(gè)消息轉(zhuǎn)換器,我們發(fā)現(xiàn)他都是實(shí)現(xiàn)了HttpMessageConverter這個(gè)接口

這里面有2個(gè)方法,canRead()和canWrite()來(lái)幫助我們判斷能否支持源類型和目標(biāo)類型的消息讀寫(xiě)

最終我們確定了,使用MappingJackson2HttpMessageConverter這個(gè)消息轉(zhuǎn)換器來(lái)進(jìn)行json轉(zhuǎn)換

package org.springframework.http.converter;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
public interface HttpMessageConverter<T> {
	// 讀取,將我們當(dāng)前消息轉(zhuǎn)換器支持的對(duì)象以某種格式讀取進(jìn)來(lái),例如將json數(shù)據(jù)讀取成Person對(duì)象
    boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
	// 寫(xiě)出,我們當(dāng)前消息轉(zhuǎn)換器支持的對(duì)象以某種格式寫(xiě)出去,例如將Person對(duì)象以json格式寫(xiě)出去
    boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
    List<MediaType> getSupportedMediaTypes();
    default List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
        return !this.canRead(clazz, (MediaType)null) && !this.canWrite(clazz, (MediaType)null) ? Collections.emptyList() : this.getSupportedMediaTypes();
    }
    T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
    void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}

然后我們?cè)诖颂幷{(diào)用MappingJackson2HttpMessageConverter父類AbstractGenericHttpMessageConverter中的write()方法

走到AbstractJackson2HttpMessageConverter類下的writeInternal()方法

可以看出,它利用了底層的Jackson的objectMapper進(jìn)行轉(zhuǎn)換

這樣,我們就完成了Person數(shù)據(jù)到j(luò)son格式的轉(zhuǎn)換

大概流程如下

  • 判斷當(dāng)前響應(yīng)頭中是否已經(jīng)有確定的媒體類型,即MediaType
  • 獲取客戶端(PostMan、瀏覽器)支持接收的內(nèi)容類型(獲取客戶端Accept請(qǐng)求頭字段)
  • 遍歷循環(huán)所有當(dāng)前系統(tǒng)的 MessageConverter,看誰(shuí)支持操作這個(gè)對(duì)象(Person),找到支持操作Person的converter,把該converter支持的媒體類型統(tǒng)計(jì)出來(lái)放到集合中,這樣就獲取到服務(wù)端能提供哪些媒體類型
  • 進(jìn)行內(nèi)容協(xié)商,找到最佳匹配媒體類型
  • 用 支持 將對(duì)象轉(zhuǎn)為 最佳匹配媒體類型 的converter,調(diào)用它進(jìn)行轉(zhuǎn)化

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

如果需要返回xml格式的數(shù)據(jù),那么需要額外導(dǎo)入相關(guān)依賴

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

我們可以看到,瀏覽器是默認(rèn)支持如下返回格式的,一般情況下,我們無(wú)法指定自己需要的返回格式

但是我們可以通過(guò)修改配置+添加參數(shù)的方式指定我們需要的格式

首先,我們?cè)趛aml文件中,開(kāi)啟基于瀏覽器參數(shù)方式內(nèi)容協(xié)商功能

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true

一旦此參數(shù)設(shè)置為true,那么我們的內(nèi)容協(xié)商管理器contentNegotiationManager中,除了原有的從請(qǐng)求頭獲取媒體類型的策略之外,還多了一個(gè)從請(qǐng)求參數(shù)中獲取媒體類型的策略,它支持xml和json兩種媒體類型

然后我們使用http://localhost:8080/testPathVariable/001/split/decade?format=xml或者http://localhost:8080/testPathVariable/001/split/decade?format=json指定我們需要的返回格式

到此這篇關(guān)于SpringBoot響應(yīng)處理實(shí)現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)SpringBoot響應(yīng)處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入解析Java接口(interface)的使用

    深入解析Java接口(interface)的使用

    這篇文章主要介紹了深入解析Java接口(interface)的使用,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • Spring Boot Admin微服務(wù)應(yīng)用監(jiān)控的實(shí)現(xiàn)

    Spring Boot Admin微服務(wù)應(yīng)用監(jiān)控的實(shí)現(xiàn)

    這篇文章主要介紹了Spring Boot Admin微服務(wù)應(yīng)用監(jiān)控,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 一文帶你了解Spring中Bean名稱加載機(jī)制

    一文帶你了解Spring中Bean名稱加載機(jī)制

    這篇文章主要給大家介紹了Spring Framework如何從使用注解定義的Bean元數(shù)據(jù)中獲取到Bean的名稱,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-01-01
  • spring框架學(xué)習(xí)總結(jié)

    spring框架學(xué)習(xí)總結(jié)

    Spring是于2003 年興起的一個(gè)輕量級(jí)的Java 開(kāi)發(fā)框架,由Rod Johnson創(chuàng)建。簡(jiǎn)單來(lái)說(shuō),Spring是一個(gè)分層的JavaSE/EE full-stack(一站式) 輕量級(jí)開(kāi)源框架
    2021-06-06
  • JAVA數(shù)據(jù)結(jié)構(gòu)之漢諾塔代碼實(shí)例

    JAVA數(shù)據(jù)結(jié)構(gòu)之漢諾塔代碼實(shí)例

    這篇文章主要介紹了JAVA數(shù)據(jù)結(jié)構(gòu)之漢諾塔,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java未賦值變量的初始值解析(默認(rèn)值)

    Java未賦值變量的初始值解析(默認(rèn)值)

    這篇文章主要介紹了Java未賦值變量的初始值(默認(rèn)值),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java基礎(chǔ)知識(shí)精通數(shù)組的使用

    Java基礎(chǔ)知識(shí)精通數(shù)組的使用

    數(shù)組對(duì)于每一門(mén)編程語(yǔ)言來(lái)說(shuō)都是重要的數(shù)據(jù)結(jié)構(gòu)之一,當(dāng)然不同語(yǔ)言對(duì)數(shù)組的實(shí)現(xiàn)及處理也不盡相同。Java?語(yǔ)言中提供的數(shù)組是用來(lái)存儲(chǔ)固定大小的同類型元素
    2022-04-04
  • JVM默認(rèn)時(shí)區(qū)為:Asia/Shanghai與java程序中GMT+08不一致異常

    JVM默認(rèn)時(shí)區(qū)為:Asia/Shanghai與java程序中GMT+08不一致異常

    這篇文章主要介紹了JVM默認(rèn)時(shí)區(qū)為:Asia/Shanghai與java程序中GMT+08不一致異常問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 如何將Set直接轉(zhuǎn)成數(shù)組

    如何將Set直接轉(zhuǎn)成數(shù)組

    這篇文章主要介紹了如何將Set直接轉(zhuǎn)成數(shù)組,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 手把手教你寫(xiě)一個(gè)spring IOC容器的方法

    手把手教你寫(xiě)一個(gè)spring IOC容器的方法

    這篇文章主要介紹了手把手教你寫(xiě)一個(gè)spring IOC容器的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04

最新評(píng)論

新沂市| 乌拉特中旗| 宁武县| 正宁县| 伊宁县| 福建省| 册亨县| 韩城市| 易门县| 大渡口区| 新竹市| 玛沁县| 故城县| 中卫市| 盐津县| 珠海市| 阜南县| 昔阳县| 马公市| 四会市| 库伦旗| 额敏县| 庆云县| 维西| 定安县| 阳谷县| 延庆县| 崇左市| 诸暨市| 襄汾县| 邹城市| 偏关县| 德庆县| 泽普县| 乌兰察布市| 抚远县| 类乌齐县| 东平县| 靖远县| 宜黄县| 屏山县|