接着前一篇博客:SpringMVC:请求参数解析原理
测试方法:
@PostMapping("save")
@ResponseBody
public Person save(Person person){
return person;
}
上篇博客通过对SpringMVC断点跟踪,找到了请求参数解析是通过众多请求参数解析器处理的。而我们发现在RequestMappingHandlerAdapter
类中的invokeHandlerMethod
,会在invocableMethod加载众多参数解析器和返回值处理器。
![image-20210407101743685](https://gitee.com/wj204811/wj204811/raw/master/img/20210407101743.png)
返回值处理器总共有15种:都实现了HandlerMethodReturnValueHandler
接口
HandlerMethodReturnValueHandler
接口有两个方法:supportsReturnType
和handleReturnValue
获取返回值处理器和处理返回值,跟请求参数解析器的源码很像,都是遍历所有的处理器,找到对应的的处理器,然后调用该处理器的处理方法。
![image-20210407102027816](https://gitee.com/wj204811/wj204811/raw/master/img/20210407102027.png)
因为我这里标注了@ResponseBody
,所以由RequestResponseBodyMethodProcessor
处理器进行处理,具体判断逻辑,这里就不看了,也比较简单。
我们关注的是它的handleRetureValue是怎么执行的?具体调用了writeWithMessageConverters
方法来处理返回值。根据方法名,可以得出是通过MessageConverters
消息转换器进行处理。
那我们就要看MessageConverters
消息转换器是如何工作的。
断点继续往下走:媒体类型的判断
这里acceptableTypes
是浏览器能接收的返回值类型:
producibleTypes
是后端能返回的类型:
服务器会根据自身能力,决定生产出什么样的内容类型的数据mediaTypesToUse
。
mediaType找到后,重点来了。
消息转换器接口:主要功能就是将Class对象转换为MediaType类型的数据。
public interface HttpMessageConverter<T> {
//是否能读
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
//是否能写
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
//获取所有支持转换的MediaType
List<MediaType> getSupportedMediaTypes();
//读操作
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
//写操作
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
断点继续往下走,发现最终由MappingJackson2HttpMessageConverter
这个类型来处理,写出操作用的是write
方法
![image-20210407105602565](https://gitee.com/wj204811/wj204811/raw/master/img/20210407105602.png)
![image-20210407105910461](https://gitee.com/wj204811/wj204811/raw/master/img/20210407105910.png)
整个过程下来:MappingJackson2HttpMessageConverter
可以将对象转为json,再将json写出去