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

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 即可。

http://www.xdnf.cn/news/6369.html

相关文章:

  • 区块链blog1__合作与信任
  • 电池组PACK自动化生产线:多领域电池生产的“智能引擎”
  • 【美团】后端一面复盘|项目驱动 + 手撕 + JVM + 数据库全面覆盖
  • 重磅发布!OpenAI 推出最新模型 GPT-4.1 系列!
  • 多模态大语言模型arxiv论文略读(七十七)
  • 【氮化镓】HfO2钝化优化GaN 器件性能
  • 【React全栈进阶】从组件设计到性能优化实战指南
  • 什么是TCP协议?它存在哪些安全挑战?
  • K8S Gateway API 快速开始、胎教级教程
  • 无人设备遥控器之无线通讯技术篇
  • 随机矩阵放大的方式 生成相位数据集,用于相位展开
  • 技术更新频繁,团队如何适应变化
  • 什么是接口文档,如何使用,注意事项有哪些
  • 【NLP 74、最强提示词工程 Prompt Engineering 从理论到实战案例】
  • spark和hadoop之间的区别和联系
  • 20250507训练赛补题
  • CCF BDCI基于运营商文本数据的知识库检索(RAG)大赛亚军方案分享
  • 联排半孔PCB如何进行SMT贴片?
  • SymPy | 如何提取指定项的系数
  • 【CTFer成长之路】命令执行RCE
  • 动态规划问题 -- 多状态模型(粉刷房子)
  • ⭐️⭐️⭐️【课时6:如何创建工作流应用】学习总结 ⭐️⭐️⭐️ for《大模型Clouder认证:基于百炼平台构建智能体应用》认证
  • 基于Cholesky分解求解逆矩阵
  • 【autojs】图色识别状态条
  • java课堂笔记6
  • 高并发场景下的数据一致性问题
  • 魔改离线VLLM
  • 在RAG中 如何提高向量搜索的准确性?
  • STC32G12K128实战:串口通信
  • 旗舰PCIe 5.0新宠:系统盘与副盘如何选?金士顿Kingston FURY Renegade G5 SSD深度解析与分区建议