SpringBoot響應(yīng)處理之以Json數(shù)據(jù)返回的實(shí)現(xiàn)方法
一、示例代碼
訪(fǎng)問(wèn) localhost:8080/jsonTest —— 返回 json 格式的數(shù)據(jù)
@Controller
public class ResponseTestController {
@ResponseBody // 標(biāo)注 —— 自動(dòng)返回json數(shù)據(jù)
@GetMapping("/jsonTest")
public Person testPerson(){
Person person = new Person();
person.setAge(20);
person.setUserName("Liuwanqing");
Pet pet = new Pet();
pet.setName("huahua");
pet.setAge("五個(gè)月");
person.setPet(pet);
return person;
}
}
二、返回值解析原理
SpringBoot 支持的返回值類(lèi)型是由返回值解析器決定的,SpringBoot 返回值類(lèi)型如下:
ModelAndView
Model
View
…
SpringBoot共含15種返回值解析器決定了其支持15種返回值:

三、源代碼分析(debug)
設(shè)置以下幾處斷點(diǎn):

step into —— 返回值處理器邏輯
this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
1. 先找返回值處理器
HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
2. 執(zhí)行下列代碼,找到符合要求的返回值處理器
在眾多返回值處理器中找到符合要求的 —RequestResponseBodyMethodRrocessor
即 RequestResponseBodyMethodRrocessor 可處理標(biāo)注了 @ResponseBody 注解的返回值
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = this.isAsyncReturnValue(value, returnType);
Iterator var4 = this.returnValueHandlers.iterator();
HandlerMethodReturnValueHandler handler;
do {
do {
if (!var4.hasNext()) {
return null;
}
handler = (HandlerMethodReturnValueHandler)var4.next();
} while(isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler));
} while(!handler.supportsReturnType(returnType));
return handler;
}
3. 調(diào)用返回值處理器(interface HandlerMethodReturnValueHandler)處理:
判斷是否支持這種類(lèi)型的返回值,支持調(diào)用返回值處理器,調(diào)用 handleReturnValue 進(jìn)行處理
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter var1);
void handleReturnValue(@Nullable Object var1, MethodParameter var2, ModelAndViewContainer var3, NativeWebRequest var4) throws Exception;
}
4. RequestResponseBodyMethodRrocessor工作原理
關(guān)鍵代碼:
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = this.createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = this.createOutputMessage(webRequest);
this.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
處理返回值的方法
使用消息轉(zhuǎn)換器(涉及內(nèi)容協(xié)商機(jī)制,請(qǐng)移步下文內(nèi)容協(xié)商機(jī)制)進(jìn)行寫(xiě)出操作,消息轉(zhuǎn)換器工作過(guò)程如下:
- 瀏覽器告知服務(wù)器其處理能力
- 服務(wù)器根據(jù)其自身能力,判斷服務(wù)器能生產(chǎn)什么樣的內(nèi)容
- SpringMVC 遍歷所有容器的底層 HttpMessageConverter, 看誰(shuí)能處理
四、內(nèi)容協(xié)商機(jī)制
1. 內(nèi)容協(xié)商
瀏覽器告知服務(wù)器其需要什么類(lèi)型的服務(wù)類(lèi)型
瀏覽器可接受的類(lèi)型:

服務(wù)器得到瀏覽器的處理能力:

服務(wù)器將返回內(nèi)容轉(zhuǎn)為瀏覽器能處理的形式

2. 內(nèi)容協(xié)商原理重點(diǎn)源代碼
protected List<MediaType> getProducibleMediaTypes(HttpServletRequest request, Class<?> valueClass, @Nullable Type targetType) {
Set<MediaType> mediaTypes = (Set)request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
if (!CollectionUtils.isEmpty(mediaTypes)) {
return new ArrayList(mediaTypes);
} else if (this.allSupportedMediaTypes.isEmpty()) {
return Collections.singletonList(MediaType.ALL);
} else {
List<MediaType> result = new ArrayList();
Iterator var6 = this.messageConverters.iterator();
while(true) {
while(var6.hasNext()) {
HttpMessageConverter<?> converter = (HttpMessageConverter)var6.next();
if (converter instanceof GenericHttpMessageConverter && targetType != null) {
if (((GenericHttpMessageConverter)converter).canWrite(targetType, valueClass, (MediaType)null)) {
result.addAll(converter.getSupportedMediaTypes());
}
} else if (converter.canWrite(valueClass, (MediaType)null)) {
result.addAll(converter.getSupportedMediaTypes());
}
}
return result;
}
}
}3. HttpMessageConverters消息轉(zhuǎn)換器原理
MessageConverter 規(guī)范

默認(rèn)的MessageConverter

最終 MappingJackson2HttpMessageConverter 把對(duì)象轉(zhuǎn)為JSON(利用底層的jackson的objectMapper轉(zhuǎn)換的)
總結(jié):
- 返回值處理器判斷是否支持這種類(lèi)型的返回值( supportsReturnType)
- 返回值處理器調(diào)用handleReturnValue 進(jìn)行處理
- 以 @ResponseBody 注解為例,RequestResponseBodyMethodProcessor 可以處理返回值標(biāo)
- 最后,利用 MessageConverters 進(jìn)行處理 將數(shù)據(jù)寫(xiě)為json
到此這篇關(guān)于SpringBoot響應(yīng)處理之以Json數(shù)據(jù)返回的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)SpringBoot Json數(shù)據(jù)返回內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)圖片寫(xiě)入高清字體及帶邊框的方法
這篇文章主要介紹了java實(shí)現(xiàn)圖片寫(xiě)入高清字體及帶邊框的方法,涉及java針對(duì)圖片及文字的相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
Netty分布式Future與Promise執(zhí)行回調(diào)相關(guān)邏輯剖析
這篇文章主要為大家介紹了Netty分布式Future與Promise執(zhí)行回調(diào)相關(guān)邏輯剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
spring cloud consul使用ip注冊(cè)服務(wù)的方法示例
這篇文章主要介紹了spring cloud consul使用ip注冊(cè)服務(wù)的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
java 將byte中的有效長(zhǎng)度轉(zhuǎn)換為String的實(shí)例代碼
下面小編就為大家?guī)?lái)一篇java 將byte中的有效長(zhǎng)度轉(zhuǎn)換為String的實(shí)例代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11

