当前位置: 首页 > news >正文

Spring MVC HttpMessageConverter 的作用是什么?

HttpMessageConverter (HTTP 消息转换器) 是 Spring MVC 框架中一个非常核心的组件,它的主要作用是在 HTTP 请求、响应体与 Java 对象之间进行双向转换。

核心作用:

  1. 读取请求体 (Request Body) 到 Java 对象:

    • 当 Controller 方法的参数使用 @RequestBody 注解时,Spring MVC 会尝试找到一个合适的 HttpMessageConverter 来读取 HTTP 请求体的内容 (例如,JSON 或 XML 字符串),并将其反序列化 (deserialize) 成方法参数指定的 Java 对象类型。
    • 例如,一个 POST 请求发送了 JSON 数据 { "name": "John", "age": 30 },如果 Controller 方法参数是 @RequestBody User user,那么某个 HttpMessageConverter (如 MappingJackson2HttpMessageConverter) 会负责将这个 JSON 转换为一个 User 对象。
  2. 将 Java 对象写入响应体 (Response Body):

    • 当 Controller 方法使用 @ResponseBody 注解 (或者 Controller 类使用 @RestController 注解) 标记时,Spring MVC 会尝试找到一个合适的 HttpMessageConverter 来将方法的返回值 (通常是一个 Java 对象) 序列化 (serialize) 成特定格式 (例如,JSON 或 XML 字符串),并将其写入 HTTP 响应体。
    • 例如,一个 Controller 方法返回一个 User 对象,如果内容协商确定应该返回 JSON,那么某个 HttpMessageConverter 会将 User 对象转换为 JSON 字符串并发送给客户端。

它是如何实现自动转换的 (特别是 JSON/XML)?

这个自动转换过程涉及到以下几个关键步骤和组件:

  1. 注册 HttpMessageConverter 实例:

    • Spring MVC (在 Spring Boot 环境下,通常是自动) 会在应用启动时初始化并注册一个 HttpMessageConverter 列表。
    • 这些转换器是针对不同数据格式的,例如:
      • MappingJackson2HttpMessageConverter: 用于 JSON 格式的转换,它底层使用 Jackson 库。
      • Jaxb2RootElementHttpMessageConverter: 用于 XML 格式的转换,它底层使用 JAXB (Java Architecture for XML Binding)。
      • MappingJackson2XmlHttpMessageConverter: 也是用于 XML,但使用 Jackson 的 XML 模块。
      • StringHttpMessageConverter: 用于纯文本字符串。
      • ByteArrayHttpMessageConverter: 用于字节数组。
      • 还有其他用于表单数据、Protobuf 等的转换器。
    • Spring Boot 会根据类路径上的依赖自动配置这些转换器。例如,如果 jackson-databind 在类路径上,MappingJackson2HttpMessageConverter 就会被自动注册。
  2. 内容协商 (Content Negotiation) 确定目标媒体类型:

    • 对于响应 (对象 -> 响应体):
      • Spring MVC 通过 ContentNegotiationManager 来确定应该返回给客户端的媒体类型 (MIME type)。
      • 它会考虑:
        • Controller 方法上 @RequestMapping (或其变体) 的 produces 属性。
        • 客户端请求的 Accept HTTP 头。
        • URL 路径扩展名 (如 .json, .xml) 或 URL 参数 (如 ?format=json) (如果配置了这些策略)。
      • 一旦确定了目标媒体类型 (例如 application/json)。
    • 对于请求 (请求体 -> 对象):
      • Spring MVC 会查看请求的 Content-Type HTTP 头,以了解请求体中的数据是什么格式 (例如 application/json)。
  3. 选择合适的 HttpMessageConverter

    • 对于响应:
      • Spring MVC 会遍历已注册的 HttpMessageConverter 列表。
      • 对于每个转换器,它会调用其 canWrite(Class<?> clazz, MediaType mediaType) 方法。
      • canWrite 方法会检查该转换器是否能够将给定的 Java 对象类型 (clazz,即 Controller 方法的返回值类型) 序列化为之前内容协商确定的目标媒体类型 (mediaType)。
      • 找到第一个返回 true 的转换器,就用它来进行转换。
    • 对于请求:
      • Spring MVC 同样会遍历已注册的 HttpMessageConverter 列表。
      • 对于每个转换器,它会调用其 canRead(Class<?> clazz, MediaType mediaType) 方法。
      • canRead 方法会检查该转换器是否能够将请求的 Content-Type (mediaType) 反序列化为 Controller 方法参数的目标 Java 对象类型 (clazz)。
      • 找到第一个返回 true 的转换器,就用它来进行转换。
  4. 执行转换 (序列化/反序列化):

    • 对于响应 (使用选定的转换器的 write 方法):
      • 调用选定转换器的 write(T t, MediaType contentType, HttpOutputMessage outputMessage) 方法。
      • t 是 Controller 返回的 Java 对象。
      • contentType 是协商好的响应媒体类型。
      • outputMessage 提供了写入 HTTP 响应体的方式。
      • JSON 示例 (使用 MappingJackson2HttpMessageConverter):
        • Jackson 的 ObjectMapper 会被用来将 Java 对象序列化为 JSON 字符串。
        • 这个 JSON 字符串会被写入到 HttpOutputMessage 的输出流中。
      • XML 示例 (使用 Jaxb2RootElementHttpMessageConverter):
        • JAXB 的 Marshaller 会被用来将带有 JAXB 注解的 Java 对象序列化为 XML 字符串。
        • 这个 XML 字符串会被写入到输出流中。
    • 对于请求 (使用选定的转换器的 read 方法):
      • 调用选定转换器的 read(Class<? extends T> clazz, HttpInputMessage inputMessage) 方法。
      • clazz 是 Controller 方法参数的目标 Java 对象类型。
      • inputMessage 提供了读取 HTTP 请求体的方式。
      • JSON 示例 (使用 MappingJackson2HttpMessageConverter):
        • Jackson 的 ObjectMapper 会从 HttpInputMessage 的输入流中读取 JSON 数据。
        • 然后将 JSON 数据反序列化为指定 clazz 类型的 Java 对象。
      • XML 示例 (使用 Jaxb2RootElementHttpMessageConverter):
        • JAXB 的 Unmarshaller 会从输入流中读取 XML 数据。
        • 然后将 XML 数据反序列化为指定 clazz 类型的 (带有 JAXB 注解的) Java 对象。

简而言之,整个过程可以概括为:

  1. 配置阶段: 注册一系列支持不同媒体类型的 HttpMessageConverter
  2. 请求处理阶段 (读取请求体):
    • 获取请求的 Content-Type
    • 根据 Content-Type 和目标对象类型,选择一个 HttpMessageConverter
    • 使用该转换器将请求体内容(如JSON/XML)反序列化为Java对象。
  3. 响应处理阶段 (写入响应体):
    • 通过内容协商确定响应的 Content-Type
    • 根据返回对象类型和协商好的 Content-Type,选择一个 HttpMessageConverter
    • 使用该转换器将Java对象序列化为响应体内容(如JSON/XML)。

开发中如果我们需要支持新的数据格式,只需要实现并注册一个新的 HttpMessageConverter 即可。

相关文章:

  • 2025年,如何制作并部署一个完整的个人博客网站
  • 智能视觉赋能精准抓取:富唯智能重新定义机械臂应用新高度​
  • 嵌入式学习笔记 D21:双向链表的基本操作
  • 深入浅出:Windows系统DLL劫持提权原理
  • 位运算题目:找到最接近目标值的函数值
  • 面试从微前端拓展到iframe是如何通信的
  • 计量——检验与代理变量
  • 【备忘踩坑】Android单元测试中读取测试assets的方法
  • EdgeShard:通过协作边缘计算实现高效的 LLM 推理
  • NY244NY249美光闪存颗粒NY252NY256
  • U9C与钉钉审批流对接完整过程
  • 数据结构—排序(斐波那契数列,冒泡,选择,插入,快速,归并,图,广度优先算法)
  • 【Docker】Docker安装Redis
  • Git命令总结
  • 2025年大厂C++面试题总结与解析
  • 【C++】解析C++面向对象三要素:封装、继承与多态实现机制
  • Remote Desktop安卓远程无法使用中文输入法
  • deepseek讲解如何快速解决内存泄露,内存溢出问题
  • C#数据类型
  • Python中常用的数据类型
  • 受关税政策影响,沃尔玛将上调部分商品在美售价
  • 会谈时间迟迟未定、核心议题存在分歧,俄乌“土耳其谈判”一波三折
  • 韧性十足的中国外贸企业:“不倒翁”被摁下去,还会再弹起来
  • 证监会发布《上市公司募集资金监管规则》,6月15日起施行
  • 刘晓庆被实名举报涉嫌偷税漏税,税务部门启动调查
  • 马上评|安排见义勇为学生补考,善意与善意的双向奔赴