SpringBoot响应处理之以Json数据返回的实现方法
作者:刘婉晴 发布时间:2023-12-21 12:21:47
一、示例代码
访问 localhost:8080/jsonTest —— 返回 json 格式的数据
@Controller
public class ResponseTestController {
@ResponseBody // 标注 —— 自动返回json数据
@GetMapping("/jsonTest")
public Person testPerson(){
Person person = new Person();
person.setAge(20);
person.setUserName("Liuwanqing");
Pet pet = new Pet();
pet.setName("huahua");
pet.setAge("五个月");
person.setPet(pet);
return person;
}
}
二、返回值解析原理
SpringBoot 支持的返回值类型是由返回值解析器决定的,SpringBoot 返回值类型如下:
ModelAndView
Model
View
…
SpringBoot共含15种返回值解析器决定了其支持15种返回值:
三、源代码分析(debug)
设置以下几处断点:
step into —— 返回值处理器逻辑
this.returnValueHandlers.handleReturnValue(returnValue, this.getReturnValueType(returnValue), mavContainer, webRequest);
1. 先找返回值处理器
HandlerMethodReturnValueHandler handler = this.selectHandler(returnValue, returnType);
2. 执行下列代码,找到符合要求的返回值处理器
在众多返回值处理器中找到符合要求的 —RequestResponseBodyMethodRrocessor
即 RequestResponseBodyMethodRrocessor 可处理标注了 @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. 调用返回值处理器(interface HandlerMethodReturnValueHandler)处理:
判断是否支持这种类型的返回值,支持调用返回值处理器,调用 handleReturnValue 进行处理
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter var1);
void handleReturnValue(@Nullable Object var1, MethodParameter var2, ModelAndViewContainer var3, NativeWebRequest var4) throws Exception;
}
4. RequestResponseBodyMethodRrocessor工作原理
关键代码:
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);
}
处理返回值的方法
使用消息转换器(涉及内容协商机制,请移步下文内容协商机制)进行写出操作,消息转换器工作过程如下:
浏览器告知服务器其处理能力
服务器根据其自身能力,判断服务器能生产什么样的内容
SpringMVC 遍历所有容器的底层 HttpMessageConverter, 看谁能处理
四、内容协商机制
1. 内容协商
浏览器告知服务器其需要什么类型的服务类型
浏览器可接受的类型:
服务器得到浏览器的处理能力:
服务器将返回内容转为浏览器能处理的形式
2. 内容协商原理重点源代码
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消息转换器原理
MessageConverter 规范
默认的MessageConverter
最终 MappingJackson2HttpMessageConverter 把对象转为JSON(利用底层的jackson的objectMapper转换的)
总结:
返回值处理器判断是否支持这种类型的返回值( supportsReturnType)
返回值处理器调用handleReturnValue 进行处理
以 @ResponseBody 注解为例,RequestResponseBodyMethodProcessor 可以处理返回值标
最后,利用 MessageConverters 进行处理 将数据写为json
来源:https://blog.csdn.net/liuwanqing233333/article/details/127090965


猜你喜欢
- using System;using System.Collections.Generic;using System.ComponentMo
- 1.可变参数模板C++11的新特性可变参数模板能够让我们创建可以接受可变参数的函数模板和类模板,相比C++98和C++03,类模板和函数模板
- 1.对象序列化的介绍(1).NET支持对象序列化的几种方式二进制序列化:对象序列化之后是二进制形式的,通过BinaryFormatter类来
- 在Android开发过程中,我们有时候需要获取当前的Activity实例,比如弹出Dialog操作,必须要用到这个。关于如何实现由很多种思路
- 一,FileWritter写入文件FileWritter, 字符流写入字符到文件。默认情况下,它会使用新的内容取代所有现有的内容,然而,当指
- 1.idea新建Maven项目Mybatis-study 将项目里的src文件夹删掉 依次将此项目作为父项目2.在Mybatis-study
- Vector(向量)是 java.util 包中的一个类,该类实现了类似动态数组的功能。向量和数组相似,都可以保存一组数据(数据列表)。但是
- 从不规则的字符串中截取出日期最近在项目中需要远程调接口,从String字符串中截取出日期,想了好久,最后用java8新特性,解决了,java
- /* - - - - - - - - - 
- 本文需求实现了java通过方向键控制小球移动的具体过程,供大家参考,具体内容如下需求分析:第一 要画出一个小球第二 要能通过控制方向键控制它
- 双保险线程,每次启动2个相同的线程,互相检测,避免线程死锁造成影响。两个线程都运行,但只有一个线程执行业务,但都会检测对方的时间戳 如果时间
- 第1部分 HashMap介绍HashMap简介HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。HashMap
- 自己写的一个日历记事本效果图 具体步骤:1.添加控件SkinEngine。 1.右键“工具箱”。“添加选项卡”,取名“皮肤”。
- 本文实例为大家分享了安装和配置maven环境的具体步骤,供大家参考,具体内容如下下载maven:1.进入官网下载:http://maven.
- 目录Java8新特性重复注解与类型注解一、JDK5中的注解1.注解(@)2.作用3.如何理解注解?4.关于注解5.注解分为三个阶段6.注解的
- Spring Security OAuth 默认提供OAuth2.0 的四大基本授权方式(authorization_code\implic
- 发一个库存程序,好像是几个礼拜之前写的吧,是一个用安卓实现的简易的计算器,写这个小程序之前,看了很多人写的计算器,觉得使用一个 EditTe
- 用户关闭软件时,软件一般会给“是否确认关闭”的提示。通常,我们把它写在FormClosing 事件中,如果确定关闭,就关闭;否则把FormC
- 在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。但是在通过了Ap
- 第一篇讲了文件的基本概念,和文件如何打开和关闭。第二篇主要介绍文件的顺序读写和随机读写。外加文件缓冲区的知识点。文件的顺序读写字符输入输出f