HTTP 消息转换 (HTTP Message Conversion)
spring-web 模块包含 HttpMessageConverter 接口,用于通过 InputStream 和 OutputStream 读取和写入 HTTP 请求与响应的主体。
HttpMessageConverter 在客户端(如 RestClient)和服务器端(如 Spring MVC 的 REST 控制器)都被广泛使用。
常用实现类
框架提供了主流媒体类型(MIME Types)的具体实现:
| 实现类 | 媒体类型 (Media Type) | 说明 |
|---|---|---|
StringHttpMessageConverter | text/* | 读取和写入字符串。默认编码通常为 UTF-8。 |
JacksonJsonHttpMessageConverter | application/json | 使用 Jackson 的 JsonMapper 进行 JSON 的读写。 |
FormHttpMessageConverter | application/x-www-form-urlencoded | 读写表单数据,映射到 MultiValueMap<String, String>。 |
ByteArrayHttpMessageConverter | */* | 读写字节数组。写入时默认为 application/octet-stream。 |
JacksonXmlHttpMessageConverter | application/xml | 使用 Jackson 的 XML 扩展进行 XML 读写。 |
ProtobufHttpMessageConverter | application/x-protobuf | 读写 Google Protobuf 二进制格式数据。 |
内容协商
在服务器端,Spring MVC 会根据以下因素决定使用哪个转换器:
- 请求的
Accept标头:客户端想要什么格式? - 请求的
Content-Type标头:客户端发来的是什么格式? - Controller 方法的返回类型。
补充教学
1. 魔法的源头:@ResponseBody 与 @RequestBody
当你给方法加上 @ResponseBody 时,Spring 不再通过 ViewResolver 找页面,而是把返回值丢给 HttpMessageConverter 链。
- 策略模式:Spring 会遍历所有已注册的转换器,调用它们的
canWrite方法。第一个说“我能处理这个类型”的转换器将负责把结果写回浏览器。
2. 为什么我的 JSON 字段名变了?
通常是因为 Jackson 的默认行为。
- 技巧 1:使用
@JsonProperty("user_name")显式指定字段名。 - 技巧 2:在全局配置中修改命名策略(如驼峰转下划线):properties
spring.jackson.property-naming-strategy=SNAKE_CASE
3. 如何解决 StringHttpMessageConverter 的中文乱码?
早期版本中,该转换器默认使用 ISO-8859-1,导致中文乱码。 现代方案:在 Spring Boot 3+ 中,默认已统一为 UTF-8。如果你还在使用旧版本,可以通过配置自定义 Bean 或修改属性来解决:
properties
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-84. 常见的 415 Unsupported Media Type 错误
当你看到这个报错时,通常意味着:
- 你发送的是 JSON,但忘记在 Header 里加
Content-Type: application/json。 - 或者你的后端没引入
jackson-databind依赖,导致 Spring 找不到能处理 JSON 的转换器。