TABLE OF CONTENTS

  1. Spring默认的内置HTTP消息转换器
  2. 如何配置HTTP转换器
  3. 源码实现
  4. 扩展定制
  5. 参考资料

文章主要讲解下Spring框架中的HTTP消息转换器message-converters的使用,Spring框架的HTTP消息转换器的主要作用是将HTTP请求和响应中的消息内容与Java对象之间进行相互转换(序列化与反序列化),这些消息转换器可以处理JSON、XML、文本、二进制等数据类型。

数据转换流程:

Spring默认的内置HTTP消息转换器

添加的默认HTTP消息转换器源码:
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#addDefaultHttpMessageConverters

Spring MVC中,使用message-converters标签来配置不同的消息转换器。下面是使用中需要注意的地方:

如果多个消息转换器支持相同的媒体类型时,Spring会选择第一个匹配的消息转换器进行处理请求和响应,因此在message-converter标签中配置时需要注意顺序,当然也可以通过实现WebMvcConfigurer接口的配置类,重写configureMessageConverters方法,自定义转换器的顺序。

下面是一些默认的HTTP消息转换器(具体实现可以查看org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#addDefaultHttpMessageConverters

  • org.springframework.http.converter.StringHttpMessageConverter:这是Spring框架内置的消息转换器之一,用于处理文本数据。它能够将HTTP请求中的文本数据(通常是字符串)转换为Java字符串,并反之将Java字符串转换为HTTP响应的文本数据。
  • ByteArrayHttpMessageConverter:用于处理字节数组。
  • StringHttpMessageConverter:用于处理文本(字符串)数据。
  • FormHttpMessageConverter:用于处理表单数据。
  • Jaxb2RootElementHttpMessageConverter:用于处理XML数据(需要JAXB 2支持)。
  • MappingJackson2HttpMessageConverter:用于处理JSON数据(需要Jackson 2支持),需要依赖Jackson。
  • ResourceHttpMessageConverter:负责读取资源文件和写出资源文件数据;
  • MappingJacksonHttpMessageConverter:负责读取和写入json格式的数据;(当返回值是对象或者List,就由这个处理)
  • AtomFeedHttpMessageConverter:负责读取和写入Atom格式的数据;
  • RssChannelHttpMessageConverter:负责读取和写入RSS格式的数据;

如何配置HTTP转换器

HTTP消息转换器在spring-mvc.xml文件中进行下面配置,如果不配置则默认使用内置的HTTP消息转换器。下面了字符串的转换器为StringHttpMessageConverter,Json转换器使用FastJsonHttpMessageConverter。因为使用到了Fastjson三方类库,需要在pom文件中引入依赖。

1、XML配置方式:

spring-mvc.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
<bean id="fastJsonHttpMessageConverter"
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

pom.xml

1

2、注解配置类方式

Spring 5以上采用Java 8语法,接口方法提供了default实现,没有必要通过继承适配器类WebMvcConfigurerAdapter重写方法,直接实现WebMvcConfigurer接口重写方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
@EnableWebMvc
public class HttpMessageConverterConfig implements WebMvcConfigurer {

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
converters.add(new MappingJackson2XmlHttpMessageConverter());
converters.add(new StringHttpMessageConverter());
WebMvcConfigurer.super.configureMessageConverters(converters);
}
}

源码实现

HttpMessageConverter
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor解析请求参数的方法resolveArgument()和处理返回值的方法handleReturnValue()

在项目启动的时候通过WebMvcConfigurationSupport进行加载,当getMessageConverters()被调用的时候会通过configureMessageConverters()、addDefaultHttpMessageConverters()和extendMessageConverters()三个方法进行初始话消息转换器。生成的消息转换器放在List> messageConverters集合中

org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport

返回响应时,会通过下面的方法调用http message converter进行转换
org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite#handleReturnValue
C:/Users/Tsukasa/.m2/repository/org/springframework/spring-webmvc/5.3.24/spring-webmvc-5.3.24-sources.jar!/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodProcessor.java:275

假如报No converter for [class java.util.HashMap] with preset Content-Type 'null']之类的错误,证明没有找到合适的Http Message Converter。

1
2023-10-25 01:13:29.928 [WARN ] [http-nio-8081-exec-2] [org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver] [208] Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.HashMap] with preset Content-Type 'null']

扩展定制

整体思路分为三步:

1、继承AbstractHttpMessageConverter类,根据序列化和反序列化规则,重写构造、readInternal、writeInternal、supports等相关方法;
2、通过message-converter标签或者继承WebMvcConfigurerAdapter类,配置自定义的HTTP消息转换器;
3、编写Controller控制器,修改前端请求格式为自定义格式。

似乎在执行http message converter的读取和写入操作前后,通过RequestResponseBodyAdviceChain提供了一些切面操作,可以通过实现RequestBodyAdvice或者ResponseBodyAdvice的方法来在执行前后执行一些操作。

/org/springframework/web/servlet/mvc/method/annotation/AbstractMessageConverterMethodArgumentResolver.java:184

参考资料

SpringMVC03-HttpMessageConverter(自定义消息转换器)
Spring Mvc:HttpMessageConverter 消息转换器
SpringMVC流程分析(七):HttpMessageConverter——SpringMVC中的消息转换

声明:本站所有文章均为原创或翻译,遵循署名 - 非商业性使用 - 禁止演绎 4.0 国际许可协议,如需转载请确保您对该协议有足够了解,并附上作者名 (Tsukasa) 及原文地址