HandlerMethodReturnValueHandler是一个Handler返回值的处理接口
它的实现类如下:
我们常用的是RequestResponseBodyMethodProcessor实现类:它用来处理注解@RequestBody的方法(当然了@RestController也算)
RequestResponseBodyMethodProcessor既能处理@RequestBody返回值,也能处理@RequestBody参数注入。
HandlerMethod类
是对Handler方法的一个封装,为了在请求方式时方便的访问到方法、方法参数、方法上的注解、所属的类、方法的参数、方法参数的注解等。
public class HandlerMethod {
// Object类型,既可以是个Bean,也可以是个BeanName
private final Object bean;
// 如果是BeanName,拿就靠它拿出Bean实例了~
@Nullable
private final BeanFactory beanFactory;
private final Class<?> beanType; // 该方法所属的类
private final Method method; // 该方法本身
private final Method bridgedMethod; // 被桥接的方法,如果method是原生的,它的值同method
// 封装方法参数的类实例,**一个MethodParameter就是一个入参**
// MethodParameter也是Spring抽象出来的一个非常重要的概念
private final MethodParameter[] parameters;
@Nullable
private HttpStatus responseStatus; // http状态码(毕竟它要负责处理和返回)
@Nullable
private String responseStatusReason; // 如果状态码里还要复述原因,就是这个字段 可以为null
……
它虽然可以封装这么多东西(持有Method),但是它没有invoke调用方法的能力,只能自己手动执行。
可以看到它的子类InvocableHandlerMethod,命名就可以看出增加了invoke方法。
虽然它提供了调用了能力,但是它却依旧还没有和Servlet
的API绑定起来,毕竟使用的是Spring
自己通用的的NativeWebRequest
而子类ServletInvocableHandlerMethod才是真正为servlet编写的类,并且还增加了返回值和响应状态码的处理
HandlerMethodReturnValueHandler接口的调用过程
HandlerMethodArgumentResolver参数注入参考:
直接从RequestMappingHandlerAdapter开始,调用链如下:
1、由于下面要用到RequestMappingHandlerAdapter的returnValueHandlers属性,这里先说一下:
RequestMappingHandlerAdapter类实现了InitializingBean接口,了解过bean生命周期都知道,在bean实例化时会执行afterPropertiesSet方法,如图:
执行getDefaultReturnValueHandlers方法,初始化下面的方法参数解析器,还有初始化绑定解析器和返回值处理器就不说了:
之后创建HandlerMethodReturnValueHandlerComposite对象并把这些解析器add进去。
2、调用Handler前的准备
创建一个ServletInvocableHandlerMethod类,并把上面的returnValueHandlers属性放进去。
还有准备ModelAndViewContainer,你可以认为是上下文容器,它主要是承担着整个请求过程中数据的传递工作,例如:处理保存Model和View。
还有AsyncWebRequest和SpringMVC中异步请求有关。异步参考:
3、执行ServletInvocableHandlerMethod的invokeAndHandle方法
invokeForRequest:是进行Handler的参数注入和调用Handler的功能
主要关注handleReturnValue方法,这个才是对Handler的返回值的处理
4、HandlerMethodReturnValueHandlerComposite(组合模式)准备处理Handler返回值
挨个通过各HandlerMethodReturnValueHandler接口实现类的supportsReturnType方法去判断是否支持此返回值处理
5、找到真正处理Handler返回值的类:RequestResponseBodyMethodProcessor
setRequestHandled方法表示此类可以处理返回值,后续则不需要再此处理了
6、writeWithMessageConverters方法的作用使用消息转换器转换消息后写入response,部分代码如下
挨个查询消息转换器,通过canWrite方法判断是否支持,若是支持则使用write方法写。
GenericHttpMessageConverter消息转换器的接口实现如下:
springMVC默认的消息转换器是:MappingJackson2HttpMessageConverter
为什么?
因为在springboot自动配置中配置了消息转换器,如图:
7、write方法是AbstractGenericHttpMessageConverter的,继续会调用writeInternal方法
8、这个writeInternal方法是各个不同的转换器实现的主要方法
jackson框架是使用ObjectWriter进行序列化和反序列化的
最终jackson通过把序列化的数据写入servletResponse的OutputStream()方法缓冲区,再通过flush方式把数据返回给了客户端