该内容以@ResponseBody注解的方法为例,且返回类型为自定义对象类型
如何确定执行当前请求的方法(handler)的返回值
返回值解析器
①底层返回值处理原理
以下是全部外层代码
先执行请求并获取返回值,其次设置响应状态码
进入handleReturnValue方法(HandlerMethodReturnValueHandlerComposite类中)
先获取返回值处理器
进入当前类的selectHandler方法,先判断是不是异步返回值
进入当前类的isAsyncReturnValue方法判断是不是异步返回值,当所有的返回值处理器都判断当前返回值不是异步返回值时,返回false(即当前返回值不是异步返回值)
返回当前类的selectHandler方法,遍历查询可以处理当前返回值的返回值处理器
返回值处理器共同实现的接口
利用对应的返回值处理器对返回值进行处理
ServletInvocableHandlerMethod的invokeAndHandle方法(即上面的外部代码)中
进入HandlerMethodReturnValueHandlerComposite的handleReturnValue方法中
进入RequestResponseBodyMethodProcessor的handleReturnValue方法中
实际处理返回值的方法是AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法(使用消息转换器进行写出操作)
--------------------------------------------------------------------------------------------------------------------------------
先判断是不是String类型返回值,根据结果做相应处理
再判断是不是流类型返回值,根据结果做相应处理
内容协商部分
=========================================================================
获取媒体类型,如果之前有处理,则可以直接获取响应类型
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
如果之前没有处理,则
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
先获取浏览器可以接收什么样的返回值类型
比如:
然后再获取服务器能够响应什么类型的数据
服务器开始和浏览器进行匹配
最终得出所有匹配结果(q是权重)
获得服务器实际要发送的数据类型
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
=========================================================================
当已经确定要返回数据的类型时,开始遍历MessageConverters
查找对应的消息转换器(MessageConverter),并将返回数据进行类型转换
其中插播HttpMessageConverter实现的方法
HttpMessageConverter(消息转换器)的作用是看是否支持将此Class类型的对象转换成MediaType类型的数据
比如当MediaT
其中canRead方法判断能不能将JSON转换成对象
canWrite方法判断能不能将对象转换成JSON
其他方法见名知义
默认的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
8 - true (没看源码)
9 - 支持注解方式xml处理的。
=========================================================================
查找到支持原返回值类型【比如自定义对象类型Person】和媒体类型【application/json】的消息转换器后,如本例找到【7】消息转换器
调用当前消息转换器的canWrite方法判断能否将Person类型数据转换成application/json类型数据
先判断当前消息转换器是否支持原返回值类型(自定义对象类型Person)和浏览器所要求的媒体类型是否在当前消息转换器所支持的媒体类型中
全部匹配成功后,确定要使用的消息转换器 ,即下面步骤成功
接下来拿到要响应给浏览器的内容的内容(此时还是Person对象,还没有转换成JSON)
给响应内容加上一些header
这一步才将自定义对象转换成JSON对象
在write方法中给响应再加一些header
最终 MappingJackson2HttpMessageConverter 把对象转为JSON(利用底层的jackson的objectMapper转换的)
--------------------------------------------------------------------------------------------------------------------------------
②Springboot可以将返回值自动转换成json字符串
、jackson.jar+@ResponseBody
web-starter这个场景启动器已经自动配置了转换成JSON的jackson.jar
如:此时因为加载了web-starter场景启动器,所以jackson.jar已经配置
只要在要返回json字符串的方法上加上@ResponseBody就可以自动转换返回json字符串
->>以上内容部分来源于尚硅谷雷神说SpringBoot