HttpMessageConverter浅析

midoll 479 2023-05-18

HttpMessageConverter浅析

HttpMessageConverter作用

HttpMessageConverter可以把不同类型的body转为Java对象,也可以吧Java对象转为满足要求的body,在序列化与反序列化中有非常重要的作用。

HttpMessageConverter匹配规则

  • Http请求头中会包含Accept,告知服务器要传回什么样的数据,如Accept: application/json, text/javascript, /; q=0.01;同时会指定Content-Type告知服务器本次body传输的参数数据是什么类型,服务器可以根据数据类型转化为服务器内部对象并提取参数;
  • Server端接收到请求,会判断自己是否支持客户端传过来的参数类型(MediaType),如果没有任何一个支持,服务器将返回406(HttpMediaTypeNotSupportedException);
  • Server处理完参数和逻辑,准备根据客户端要求的Accept返回,这时服务端又会判断自己是否支持返回这种类型(MediaType),如果不支持,服务器将返回406(HttpMediaTypeNotAcceptableException);
  • HttpMessageConverter的作用就是服务器判断自己是否支持某种MediaType;
  • HttpMessageConverter不是仅仅只有一个而是一个列表,通过责任链的方式匹配:循序遍历所有HttpMessageConverter,调用其canRead()方法,若返回true表示可以处理,一旦有某个HttpMessageConverter可以处理某一请求的参数MediaType,就是用这个HttpMessageConverter的read()方法读取参数,一旦处理完数据即将返回,又用同样的方法遍历HttpMessageConverter列表,找出第一个canWrite()返回true的HttpMessageConverter,调用其write()方法返回给客户端。

HttpMessageConverter初始化时序图

image-1684394494710

  1. 在ApplicationContextrefresh期间,HttpMessageConverter开始初始化,初始化分别在三个类中进行:其中RequestMappingHandlerAdapter和HttpMessageConvertersAutoConfiguration是同时行的互不干扰,HttpMessageConverters的初始化需要在前两个类初始化完成后才能进行;
  2. RequestMappingHandlerAdapter初始化默认HttpMessageConverter列表
    -1) 调用所有WebMvcConfigurer类型的自定义配置类(@Configuration)的configureMessageConverters方法初始化 HttpMessageConverter列表;
    -2) 如果没有自定义的WebMvcConfigurer配置,调用addDefaultHttpMessageConverters方法初始化HttpMessageConverter列表,默认HttpMessageConverter列表都是根据ClassLoader中是否加载否一个特定类来判断某一个HttpMessageConverter是否需要加到默认列表中,并且在最后做了一下排序,仅仅是把xml类型的转换器放到了目前的HttpMessageConverter列表最后;
    -3) 调用所有WebMvcConfigurer类型的自定义配置类的extendMessageConverters方法扩展HttpMessageConverter列表,直接加在列表尾部
  3. HttpMessageConvertersAutoConfiguration类将所有HttpMessageConverter类型的组件(@Conponent/@Bean等),初始化到一个有上下文提供的 HttpMessageConverter列表中;
  4. HttpMessageConverters初始化时,将2和3两个列表合并,如果上下文提供的和默认列表中有重复但对象并非是同一个,会把上下文提供的HttpMessageConverter和默认列表中的HttpMessageConverter放在相邻的位置,并且会把上下文提供的放在前面;把所有上下文提供的且不在默认列表中的HttpMessageConverter放在整个合并列表的最前面,上下文提供的HttpMessageConverter顺序由类上的@Order(value=1)注解指定,value值越小越靠前,优先级越高