浅谈SpringMvc HttpMessageConverter

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈SpringMvc HttpMessageConverter相关的知识,希望对你有一定的参考价值。

参考技术A 1.HttpMessageConverter是SpringMvc框架中一个重要的组件,其主要职责是对@RequestBody的解析(该注解作用就是告诉mvc,这个参数由Http的请求头,经过HttpMessageConverter解析得到)

看一下该接口

该接口的canRead方法表示其支持的Class类型,MediaType是其支持的http的ContentType类型,假如一个Http请求是Application/json,Mvc框架会去寻找支持该MediaType的Converter,然后再判断@RequestBody注解对应的class类型是否支持,如果支持,那么就交由对应的MessageConverter去解析。

另一个问题就是,这个类是解析什么呢,实际上,HttpInputMessage是指HttpServletRequest的Body的流,可以看接口。

那么Mvc框架的部分核心我们就能猜到了,一个Http请求过来,包括Header和Body,对于其中的Body的流将会被DispatcherServlet包装成SpringMvc的HttpRequest,然后委托RequestChainExecutor,经过一系列处理,最终Body的流到了HttpMessageConverter(这里不是那么准确),重点需要理解的就是一个Http请求,头部会被HttpMessageConverter获取并解析,如果找不到对应的HttpMessageConverter,Spring框架会报异常。

一般情况下,我们常见的有StringHttpMessageConverter(text/plain+String),ByteArrayHttpMessageConverter(application/octet-stream+byte[]),FormHttpMessageConverter(好几个),FastJsonHttpMessageConverter(application/json+Object)等。

如果要自定义一个HttpMessageConverter,只要继承AbstractHttpMessageConverter就可以,其中运用了模板方法,具体的逻辑组织在AbstractHttpMessageConverter中已经实现,只需要实现以下方法和构造方法就可以使用了。

该部分就是,将HttpMessage(通过容器的HttpRequest获得相关属性),首先read请求时,直接转readInternal(子类实现),如果是write响应,则先判断返回的结果类型是不是流,是流就直接构建Message响应(返回流,如果直接读取就会被消费了,流只能读一次,对应的就是Controller(MethodHandler)的返回结果),如果是其他类型,则交由实现类将JavaObject变成流。

综上所述,HttpMessageConverter就是负责将Http请求的Body与JavaObject之间进行转换,那么在哪里可以配置呢?在WebMvcConfigurationSupport的configureMessageConverters中可以配置,默认情况boot会在存在对应classPath时自动注入mvc相关配置,而关于HttpMessageConverter在不重写configureMessageConverters时默认配置一堆,一旦自定义配置了,就只支持自己定义的几个了。

关于模板方法,在AbstractXmlHttpMessageConverter中也有使用到,同样的套路,父类定义方法模板(骨架),子类实现逻辑原语。

对于一个Http请求,Tomcat(一定猜测)首先监听端口,收到请求就委托一个Thread去初始化Servlet或者执行Servlet,并通过ThreadLocal来保存HttpServletContext和HttpRequest与HttpResponse,如果去测试的话,你会发现Tomcat基于装饰器模式用RequestFacade,ResponseFacade封装了Request和Response,请求到DispatcherServlet,SpringMvc则解析请求头(可以重复解析)和请求Body,通过请求头方法类型交给doDispatch进行解析,最终交给RequestChainExecutor去执行,通过请求头得到路径交给不同的MethodHandler(Controller接口与@Controller)去处理。根据MethodHandler对应方法的注解(@RequestBody,@ResponseBody,@PathVariable等)来交给HttpMessageConverter(Body的解析)、Converter(默认的非Body的解析)、HandlerMethodArgumentResolver(报文头解析及前置处理)、HandlerMethodReturnValueHandler(方法返回参数处理)等进行Http报文和JavaObject的转换。

我实在懒得写清除细节了,截图头疼,没必要深究源码(太细节了),先搞清楚Mvc的各个组件再说。

Mvc 数据流

Http(Header+Body)->HttpMessage(Body)->HttpMessageConverter->JavaObject

                                                       (Header)->Converter+Format SPI

Mvc Controller拓展

MethodHandler+MethodHandlerInterceptor+HandlerMethodArgumentResolver+

HandlerMethodReturnValueHandler+Aspect(有些拓展基于代理)

以上是关于浅谈SpringMvc HttpMessageConverter的主要内容,如果未能解决你的问题,请参考以下文章

浅谈SpringMVC核心组件及执行流程(含源码解析)

浅谈SpringMvc HttpMessageConverter

浅谈SpringMVC源码的DispatcherServlet组件执行流程

[ SSM ] 浅谈 SSM 框架(Spring+SpringMVC+MyBatis)

秒懂SpringBoot之Mvc请求执行流程浅谈

秒懂SpringBoot之Mvc请求执行流程浅谈