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
猜你喜欢
- 1 StringString:字符串常量,字符串长度不可变。2 StringBufferStringBuffer:字符串变量(Synchro
- 一、需求场景有时候我们需要在项目中使用一些静态资源文件,比如城市信息文件 countries.xml,在项目启动后读取其中的数据并初始化写进
- 本文实例讲述了Java枚举类用法。分享给大家供大家参考。具体如下:package com.school.stereotype; /** *
- 话不多说,请看代码:<!DOCTYPE html><html><head> <meta
- 目录Spring自动注入失败如何解决?回答注入你的bean使用@Configurable手动查找bean:不推荐Spring自动注入失败如何
- Spring 提供了自动代理机制,可以让容器自动生成代理,从而把开发人员从繁琐的配置中解脱出来 。 具体是使用 BeanPostProces
- 概念优先级队列是一种先进先出(FIFO)的数据结构,与队列不同的是,操作的数据带有优先级,通俗的讲就是可以比较大小,在出队列的时候往往需要优
- 在谈 Volatile 之前,我们先回顾下 Java 内存模型 的三要素:原子性、可见性、有序性,也就是大家常提到的并发编程三要素。并发编程
- 单选题:(每道题目2分)1. 下列哪个声明是错误的?(B) A. int i=10;B. float f=1.1;&
- 一:问题描述 在已经root过的android设备下,app执行一个linux命令,app需要获取su权限,在某些a
- 前言我们知道在 Java 中读取一些配置文件信息,是在开发中十分常用的要求。例如:这里我们使用 JDBC 实例:连接My
- 这篇文章主要介绍了Java方法重载Overload原理及使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 一、概要1.Java虚拟机(Jvm)是什么?2.Java虚拟机是用来干什么的?3.Java虚拟机它的体系结构是什么样子的?4.Java虚拟机
- ArrayList中存放引用数据类型ArrayList中存放引用类型时,存放的是一个引用,因此在放入ArrayList之后再进行改动会影响到
- [LeetCode] 5. Longest Palindromic Substring 最长回文子串Given a string
- Spring Cloud Gateway(以下简称 SCG)做为网关服务,是其他各服务对外中转站,通过 SCG 进行请求转发。在请求到达真正
- 介绍众所周知,AOP(面向切面编程)是Spring框架的特色功能之一。通过设置横切关注点(cross cutting concerns),A
- 今天有个项目需要使用redis,并且有使用脚本的需求。但是因为之前没有写过,所以还有一点点不熟悉,今天记录一下。原因:原子操作,redis会
- Failed to execute goal org.apache.maven.plugins:maven-resources-plugin
- 将图片上传到webapp路径下 路径获取方式此方法获取到工程webapp文件夹下String contexPath= request.get