概念
HttpMessageConverter
是 Spring 框架中用于处理 HTTP 请求和响应数据的核心接口,负责在 Java 对象与 HTTP 消息体(请求体或响应体)之间进行双向转换。简单来说,它是 Spring 用来将 HTTP 请求中的原始数据(如 JSON、XML、表单数据等)转换为 Java 对象,或者将 Java 对象转换为 HTTP 响应数据的“翻译器”
就是返回的是 UserVO 对象,但是最后传输到前端时,变成了 Json 字符串
核心作用
- 序列化和反序列化
- 请求:将客户端发送的 HTTP 请求体(如 JSON 字符串)反序列化为 Java 对象(如
User
类) - 响应:将 Java 对象(如
User
对象)序列化为客户端需要的格式(如 JSON、XML)
- 请求:将客户端发送的 HTTP 请求体(如 JSON 字符串)反序列化为 Java 对象(如
- 内容协商:根据客户端请求的
Content-Type
(请求数据类型)和Accept
(期望的响应数据类型),自动选择匹配的HttpMessageConverter
处理数据格式
接口源码
package org.springframework.http.converter;
import java.io.IOException;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
default List<MediaType> getSupportedMediaTypes(Class<?> clazz) {
return !this.canRead(clazz, (MediaType)null) && !this.canWrite(clazz, (MediaType)null) ? Collections.emptyList() : this.getSupportedMediaTypes();
}
T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}
根据源码解释作用:
- 在请求时,通过请求头
Content-Type
上,表示请求内容(Request Body)的内容类型。这样,Spring MVC 会从HttpMessageConverter
数组中,通过canRead(clazz, mediaType)
方法,判断是否够读取指定的mediaType
内容类型,转换成对应的clazz
对象。如果可以的话,则调用read(Class<? extends T> clazz, HttpInputMessage inputMessage)
方法,读取请求内容,转换成clazz
对象。 - 在响应时,通过请求头
Accept
上,表示请求内容(Response Body)的内容类型。Spring MVC 会从HttpMessageConverter
数组中,通过canWrite(clazz, mediaType)
方法,判断是否能够将clazz
对象,序列化成mediaType
内容类型。如果可以的话,则调用write(contentType, outputMessage)
方法,将clazz
对象,序列化成contentType
内容类型,写入到响应。
常见实现方法
内置了多种 HttpMessageConverter
实现,支持不同数据格式
实现类 | 作用 |
---|---|
MappingJackson2HttpMessageConverter |
处理 JSON 格式(基于 Jackson 库) |
GsonHttpMessageConverter |
处理 JSON 格式(基于 Gson 库) |
Jaxb2RootElementHttpMessageConverter |
处理 XML 格式(基于 JAXB) |
StringHttpMessageConverter |
处理纯文本(如 text/plain ) |
FormHttpMessageConverter |
处理表单数据(application/x-www-form-urlencoded ) |
案例
同时支持 JSON/XML 格式提交数据,也同时支持 JSON/XML 格式响应数据的案例
XmlMapper 是 Jackson 提供的用于处理 XML 的类,位于
jackson-dataformat-xml
模块中。默认情况下,SpringBoot 并不会自动包含该模块,需要手动添加相关依赖。
配置
重写 MappingJackson2XmlHttpMessageConverter 配置类,新增 XML 格式
@Configuration
@RequiredArgsConstructor
public class SpringMVCConfiguration implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder xmlBuilder = Jackson2ObjectMapperBuilder.xml();
xmlBuilder.indentOutput(true);
converters.add(new MappingJackson2XmlHttpMessageConverter(xmlBuilder.build()));
}
}
接口
新增接口
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping(
value = "/addXml",
// ↓ 增加 "application/xml"、"application/json" ,针对 Content-Type 请求头
consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
// ↓ 增加 "application/xml"、"application/json" ,针对 Accept 请求头
produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}
)
public UserVO addXml(@RequestBody UserAddDTO addDTO) {
return new UserVO().setUsername("username: " + addDTO.getUsername());
}
}
- consumes 属性:限制可接受的请求内容类型,不匹配时返回
415 Unsupported Media Type
状态码- produces 属性:限制可返回的响应内容类型,不匹配时返回
406 Not Acceptable
状态码
请求接口
POST http://localhost:8080/users/addXml
Content-Type: application/xml
Accept: application/xml
<user>
<id>1</id>
<username>张三</username>
<password>123456</password>
</user>
返回
<Result>
<code>200</code>
<msg>成功</msg>
<data>
<id/>
<username>username: 张三</username>
</data>
</Result>
Fastjson 依赖
在 SpringBoot 中默认是用 Jackson 作为对 JSON 的序列化和反序列化,即默认使用 MappingJackson2HttpMessageConverter
(基于 Jackson 库)处理 JSON 数据,有时候可以使用第三方依赖来替换 Jackson 实现对 JSON 的序列化和反序列化,比如 Fastjson 依赖。
Fastjson 是阿里巴巴开源的一款高性能 Java JSON 库,用于实现 Java 对象与 JSON 数据之间的序列化(对象 → JSON)和反序列化(JSON → 对象)。它的核心目标是提供极致的 JSON 处理性能(号称“最快的 JSON 库”),同时支持复杂的 Java 类型(如泛型、枚举、Lambda 表达式)和灵活的配置。
使用原因
- 性能优势
- 更快的处理速度:在序列化和反序列化时通常比 Jackson 更快(尤其是处理大对象或复杂结构时),适合高并发场景
- 低内存占用:Fastjson 的设计优化了内存使用,减少 GC 压力
- 功能丰富性
- 支持复杂类型:如泛型、
LocalDateTime
、枚举等,无需额外配置 - 灵活的注解:通过
@JSONField
注解可自定义字段名称、格式、忽略字段等 - 定制化配置
- 支持复杂类型:如泛型、
- 易用性
- 简洁的API:Fastjson 提供类似
JSON.toJSONString(obj)
和JSON.parseObject(json, User.class)
的直接方法 - 中文支持友好
- 简洁的API:Fastjson 提供类似
配置过程
添加 Fastjson
依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.50</version>
</dependency>
添加 Fastjson
依赖后,需要排除掉默认 Jackson
依赖(如果你不需要它的话)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency>
配置 Fastjson
@Configuration
@RequiredArgsConstructor
public class SpringMVCConfiguration implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 定义一个convert转换消息的对象
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
// 添加fastjson的配置信息
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(
// 格式化输出
SerializerFeature.PrettyFormat,
// 输出空字段
SerializerFeature.WriteMapNullValue,
// 日期格式化
SerializerFeature.WriteDateUseDateFormat
);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
// 处理中文乱码问题
List<MediaType> fastMediaTypes = new ArrayList<>();
// fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastMediaTypes.add(MediaType.APPLICATION_JSON);
fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
// 在converters中添加fastjson的配置信息
converters.add(0, fastJsonHttpMessageConverter);
}
}
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8)
会有'APPLICATION_JSON_UTF8' is deprecated
提示,因为 Framework 自 5.2 起,推荐使用MediaType.APPLICATION_JSON
,因为主要浏览器(如 Chrome)现在遵循规范,能够正确解析UTF-8
特殊字符,而无需在 Content-Type 中指定 charset=UTF-8 参数。
setSerializerFeatures
方法
config.setSerializerFeatures
是 Fastjson 中用于配置 JSON 序列化行为的核心方法,它通过启用或禁用不同的 SerializerFeature
枚举值,控制 Java 对象转换为 JSON 字符串时的具体规则
Fastjson 默认的序列化行为较为简洁(例如不输出空字段、日期使用时间戳格式),但在实际开发中,我们通常需要更灵活的配置。
场景示例 | 默认行为 | 配置特性后的行为 |
---|---|---|
空字段处理 | 忽略 null 字段 |
输出 {"name": null} |
日期格式 | 日期转为时间戳(如 1672531200000 ) |
转为 "2023-01-01 00:00:00" |
JSON 可读性 | 压缩输出(无缩进换行) | 格式化输出(带缩进和换行) |
枚举类型处理 | 输出枚举的 name() 值 |
输出枚举的 ordinal() 值 |
PrettyFormat
:格式化 JSON 输出,添加换行和缩进,使 JSON 更易阅读
// 未启用 PrettyFormat
{"name":"Alice","age":25}
// 启用 PrettyFormat
{
"name": "Alice",
"age": 25
}
WriteMapNullValue
:序列化时保留值为null
的字段
// 未启用 WriteMapNullValue
{"name":"Alice"}
// 启用 WriteMapNullValue
{"name":"Alice", "age":null}
WriteDateUseDateFormat
:将Date
类型字段按指定格式(如yyyy-MM-dd HH:mm:ss
)序列化
config.setDateFormat("yyyy-MM-dd");
// 输出
{"birthday": "2023-01-01"}
WriteEnumUsingToString
:将枚举类型按toString()
方法的值输出,而非默认的name()
enum Status { OPEN("开启"), CLOSE("关闭"); }
// 默认输出 "OPEN"
// 启用后输出 "开启"