Spring MVC HttpMessageConverter 的作用是什么?
HttpMessageConverter
(HTTP 消息转换器) 是 Spring MVC 框架中一个非常核心的组件,它的主要作用是在 HTTP 请求、响应体与 Java 对象之间进行双向转换。
核心作用:
-
读取请求体 (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
对象。
- 当 Controller 方法的参数使用
-
将 Java 对象写入响应体 (Response Body):
- 当 Controller 方法使用
@ResponseBody
注解 (或者 Controller 类使用@RestController
注解) 标记时,Spring MVC 会尝试找到一个合适的HttpMessageConverter
来将方法的返回值 (通常是一个 Java 对象) 序列化 (serialize) 成特定格式 (例如,JSON 或 XML 字符串),并将其写入 HTTP 响应体。 - 例如,一个 Controller 方法返回一个
User
对象,如果内容协商确定应该返回 JSON,那么某个HttpMessageConverter
会将User
对象转换为 JSON 字符串并发送给客户端。
- 当 Controller 方法使用
它是如何实现自动转换的 (特别是 JSON/XML)?
这个自动转换过程涉及到以下几个关键步骤和组件:
-
注册
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
就会被自动注册。
- Spring MVC (在 Spring Boot 环境下,通常是自动) 会在应用启动时初始化并注册一个
-
内容协商 (Content Negotiation) 确定目标媒体类型:
- 对于响应 (对象 -> 响应体):
- Spring MVC 通过
ContentNegotiationManager
来确定应该返回给客户端的媒体类型 (MIME type)。 - 它会考虑:
- Controller 方法上
@RequestMapping
(或其变体) 的produces
属性。 - 客户端请求的
Accept
HTTP 头。 - URL 路径扩展名 (如
.json
,.xml
) 或 URL 参数 (如?format=json
) (如果配置了这些策略)。
- Controller 方法上
- 一旦确定了目标媒体类型 (例如
application/json
)。
- Spring MVC 通过
- 对于请求 (请求体 -> 对象):
- Spring MVC 会查看请求的
Content-Type
HTTP 头,以了解请求体中的数据是什么格式 (例如application/json
)。
- Spring MVC 会查看请求的
- 对于响应 (对象 -> 响应体):
-
选择合适的
HttpMessageConverter
:- 对于响应:
- Spring MVC 会遍历已注册的
HttpMessageConverter
列表。 - 对于每个转换器,它会调用其
canWrite(Class<?> clazz, MediaType mediaType)
方法。 canWrite
方法会检查该转换器是否能够将给定的 Java 对象类型 (clazz
,即 Controller 方法的返回值类型) 序列化为之前内容协商确定的目标媒体类型 (mediaType
)。- 找到第一个返回
true
的转换器,就用它来进行转换。
- Spring MVC 会遍历已注册的
- 对于请求:
- Spring MVC 同样会遍历已注册的
HttpMessageConverter
列表。 - 对于每个转换器,它会调用其
canRead(Class<?> clazz, MediaType mediaType)
方法。 canRead
方法会检查该转换器是否能够将请求的Content-Type
(mediaType
) 反序列化为 Controller 方法参数的目标 Java 对象类型 (clazz
)。- 找到第一个返回
true
的转换器,就用它来进行转换。
- Spring MVC 同样会遍历已注册的
- 对于响应:
-
执行转换 (序列化/反序列化):
- 对于响应 (使用选定的转换器的
write
方法):- 调用选定转换器的
write(T t, MediaType contentType, HttpOutputMessage outputMessage)
方法。 t
是 Controller 返回的 Java 对象。contentType
是协商好的响应媒体类型。outputMessage
提供了写入 HTTP 响应体的方式。- JSON 示例 (使用
MappingJackson2HttpMessageConverter
):- Jackson 的
ObjectMapper
会被用来将 Java 对象序列化为 JSON 字符串。 - 这个 JSON 字符串会被写入到
HttpOutputMessage
的输出流中。
- Jackson 的
- XML 示例 (使用
Jaxb2RootElementHttpMessageConverter
):- JAXB 的
Marshaller
会被用来将带有 JAXB 注解的 Java 对象序列化为 XML 字符串。 - 这个 XML 字符串会被写入到输出流中。
- JAXB 的
- 调用选定转换器的
- 对于请求 (使用选定的转换器的
read
方法):- 调用选定转换器的
read(Class<? extends T> clazz, HttpInputMessage inputMessage)
方法。 clazz
是 Controller 方法参数的目标 Java 对象类型。inputMessage
提供了读取 HTTP 请求体的方式。- JSON 示例 (使用
MappingJackson2HttpMessageConverter
):- Jackson 的
ObjectMapper
会从HttpInputMessage
的输入流中读取 JSON 数据。 - 然后将 JSON 数据反序列化为指定
clazz
类型的 Java 对象。
- Jackson 的
- XML 示例 (使用
Jaxb2RootElementHttpMessageConverter
):- JAXB 的
Unmarshaller
会从输入流中读取 XML 数据。 - 然后将 XML 数据反序列化为指定
clazz
类型的 (带有 JAXB 注解的) Java 对象。
- JAXB 的
- 调用选定转换器的
- 对于响应 (使用选定的转换器的
简而言之,整个过程可以概括为:
- 配置阶段: 注册一系列支持不同媒体类型的
HttpMessageConverter
。 - 请求处理阶段 (读取请求体):
- 获取请求的
Content-Type
。 - 根据
Content-Type
和目标对象类型,选择一个HttpMessageConverter
。 - 使用该转换器将请求体内容(如JSON/XML)反序列化为Java对象。
- 获取请求的
- 响应处理阶段 (写入响应体):
- 通过内容协商确定响应的
Content-Type
。 - 根据返回对象类型和协商好的
Content-Type
,选择一个HttpMessageConverter
。 - 使用该转换器将Java对象序列化为响应体内容(如JSON/XML)。
- 通过内容协商确定响应的
开发中如果我们需要支持新的数据格式,只需要实现并注册一个新的 HttpMessageConverter
即可。
相关文章:
Spring MVC HttpMessageConverter 的作用是什么?
HttpMessageConverter (HTTP 消息转换器) 是 Spring MVC 框架中一个非常核心的组件,它的主要作用是在 HTTP 请求、响应体与 Java 对象之间进行双向转换。 核心作用: 读取请求体 (Request Body) 到 Java 对象: 当 Controller 方法的参数使用 …...

小乌龟git中的推送账户、作者账户信息修改
文章目录 修改git文档作者信息修改git推送用户信息参考文献 修改git文档作者信息 小乌龟中的用户信息为:作者信息,并非推送用户。 上边用户信息,修改的是文件的作者信息。如果想要修改git服务中记录的推送用户信息需要修改推送用户信息。 …...

Kubernetes MCP服务器(K8s MCP):如何使用?
#作者:曹付江 文章目录 1、什么是 Kubernetes MCP 服务器?1.1、K8s MCP 服务器 2、开始前的准备工作2.1. Kubernetes集群2.2. 安装并运行 kubectl2.3. Node.js 和 Bun2.4. (可选)Helm v3 3、如何设置 K8s MCP 服务器3.1. 克隆存储…...
Node.js聊天室开发:从零到上线的完整指南
为让你全面了解Node.js聊天室开发,我会先介绍开发背景与技术栈,再按搭建项目、实现核心功能、部署上线的流程展开,还会分享优化思路。 Node.js聊天室开发实战:从入门到上线 在即时通讯日益普及的今天,基于Node.js搭建…...

R²AIN SUITE 亮相第九届智能工厂高峰论坛
2025年5月16日,在圆满落幕的第九届智能工厂高峰论坛上,上海比孚信息科技有限公司携自主研发的 RAIN SUITE 企业AI应用中台解决方案亮相展会。本次论坛以"从互联工厂到智慧工厂"为主题,吸引了400余位行业专家、制造企业代表及产业链…...

深入理解仿函数(Functors):从概念到实践
文章目录 1. 什么是仿函数?2. 仿函数与普通函数的区别3. 标准库中的仿函数4. 仿函数的优势4.1 状态保持4.2 可定制性4.3 性能优势 5. 现代C中的仿函数5.1 Lambda表达式5.2 通用仿函数 6. 仿函数的高级应用(使用C2020标准库及以上版本)6.1 函数…...

InternLM 论文分类微调实践(XTuner 版)
1.环境安装 我创建开发机选择镜像为Cuda12.2-conda,选择GPU为100%A100的资源配置 Conda 管理环境 conda create -n xtuner_101 python3.10 -y conda activate xtuner_101 pip install torch2.4.0cu121 torchvision torchaudio --extra-index-url https://downloa…...
《Python星球日记》 第88天:ChatGPT 与 LangChain
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、ChatGPT 简介1. 如何与ChatGPT交互?2. Prompt Engineering 的技巧二、LangChain框架1. 什么是LangChain?2. LangChain的核心组件3. 如何使…...

PC:使用WinSCP密钥文件连接sftp服务器
1. 打开winscp工具,点击“标签页”->“新标签页” 2. 点击“高级"->“高级” 3. 点击"验证"->“选择密钥文件” 选择ppk文件,如果没有ppk文件选择pem文件,会自动生成ppk文件 点击确定 4. 输入要连接到的sftp服务器的…...

1688正式出海,1688跨境寻源通接口接入,守卫的是国内工厂资源
在1688平台的跨境招商直播中,许多想要进入跨境市场的初学者商家纷纷提问:货通全球的入口在哪里?小白商家应该如何操作?商品为何上传失败? 从表面上看,这似乎是1688平台在拓展海外市场的一次积极“进攻”。…...

力扣303 区域和检索 - 数组不可变
文章目录 题目介绍题解 题目介绍 题解 不用管第一个null,从第二个开始看就可以 法一:暴力解法 class NumArray {private int[] nums;public NumArray(int[] nums) {this.nums nums;}public int sumRange(int left, int right) {int res 0;for (int i…...

Spring的后置处理器是干什么用的?扩展点又是什么?
Spring 的后置处理器和扩展点是其框架设计的核心机制,它们为开发者提供了灵活的扩展能力,允许在 Bean 的生命周期和容器初始化过程中注入自定义逻辑。 1. 后置处理器(Post Processors) 后置处理器是 Spring 中用于干预 Bean 生命…...

[ linux-系统 ] 进程地址空间
验证地址空间 父子进程的变量值不同但是地址相同,说明该地址绝对不是物理地址 我们叫这种地址为虚拟地址/线性地址 分析与结论 上述实验表明,父子进程的变量地址相同但内容不同,说明地址为虚拟地址,且父子进程有各自独立的物理…...

文件名是 E:\20250512_191204.mp4, EV软件录屏,未保存直接关机损坏, 如何修复?
去github上下载untrunc 工具就能修复 https://github.com/anthwlock/untrunc/releases 如果访问不了 本机的 hosts文件设置 140.82.112.3 github.com 199.232.69.194 github.global.ssl.fastly.net 就能访问了 实在不行,从这里下载,传上去了 https://do…...

Java常见API文档(下)
格式化的时间形式的常用模式对应关系如下: 空参构造创造simdateformate对象,默认格式 练习.按照指定格式展示 package kl002;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;public class Date3 {publi…...

DRIVEGPT4: 通过大语言模型实现可解释的端到端自动驾驶
《DriveGPT4: Interpretable End-to-End Autonomous Driving via Large Language Model》 2024年10月发表,来自香港大学、浙江大学、华为和悉尼大学。 多模态大型语言模型(MLLM)已成为研究界关注的一个突出领域,因为它们擅长处理…...
知识图谱(KG)与大语言模型(LLM)
知识图谱(KG)以其结构化的知识表示和推理能力,为大语言模型(LLM)的“幻觉”、知识更新滞后和可解释性不足等问题提供了有力的解决方案。反过来,LLM的强大文本理解和生成能力也为KG的构建、补全、查询和应用…...

构建共有语料库 - Wiki 语料库
中文Wiki语料库主要指的是从中文Wikipedia(中文维基百科)提取的文本数据。维基百科是一个自由的、开放编辑的百科全书项目,覆盖了从科技、历史到文化、艺术等广泛的主题。 对于基于RAG的应用来说,把Wiki语料作为一个公有的语料库…...

苍穹外卖项目中的 WebSocket 实战:实现来单与催单提醒功能
🚀 苍穹外卖项目中的 WebSocket 实战:实现来单与催单提醒功能 在现代 Web 应用中,实时通信成为提升用户体验的关键技术之一。WebSocket 作为一种在单个 TCP 连接上进行全双工通信的协议,被广泛应用于需要实时数据交换的场景&#…...
精益数据分析(59/126):移情阶段的深度博弈——如何避开客户访谈的认知陷阱
精益数据分析(59/126):移情阶段的深度博弈——如何避开客户访谈的认知陷阱 在创业的移情阶段,客户访谈是挖掘真实需求的核心手段,但人类认知偏差往往导致数据失真。今天,我们结合《精益数据分析》的方法论…...

Win10 安装单机版ES(elasticsearch),整合IK分词器和安装Kibana
一. 先查看本机windows是否安装了ES(elasticsearch),检查方法如下: 检查进程 按 Ctrl Shift Esc 组合键打开 “任务管理器”。在 “进程” 选项卡中,查看是否有 elasticsearch 相关进程。如果有,说明系统安装了 ES。 检查端口…...
Ansible模块——主机名设置和用户/用户组管理
设置主机名 ansible.builtin.hostname: name:要设置的主机名 use:更新主机名的方式(默认会自动选择,不指定的话,物理机一般不会有问题,容器可能会有问题,一般是让它默认选择) syst…...

【Redis】List 列表
文章目录 初识列表常用命令lpushlpushxlrangerpushrpushxlpop & rpoplindexlinsertllen阻塞操作 —— blpop & brpop 内部编码应用场景 初识列表 列表类型,用于存储多个字符串。在操作和实现上,类似 C 的双端队列,支持随机访问(O(N)…...

JUC入门(四)
ReadWriteLock 代码示例: package com.yw.rw;import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteDemo {public static void main(String[] args) {MyCache myCache new MyCache…...

【HarmonyOS 5】鸿蒙mPaaS详解
【HarmonyOS 5】鸿蒙mPaaS详解 一、mPaaS是什么? mPaaS 是 Mobile Platform as a Service 的缩写,即移动开发平台。 蚂蚁移动开发平台mPaaS ,融合了支付宝科技能力,可以为移动应用开发、测试、运营及运维提供云到端的一站式解决…...
多线BGP服务器优化实践与自动化运维方案
背景:企业级网络架构中的线路选择难题 在分布式业务部署场景下,如何通过三网融合BGP服务器实现低延迟、高可用访问?本文以某电商平台流量调度优化为案例,解析动态BGP服务器的实战价值。 技术方案设计 核心架构:采用…...

无法加载文件 E:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本
遇到“无法加载文件 E:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本”这类错误,通常是因为你的 PowerShell 执行策略设置为不允许运行脚本。在 Windows 系统中,默认情况下,出于安全考虑,PowerShell 可能会阻止运行未…...

【C++模板与泛型编程】实例化
目录 一、模板实例化的基本概念 1.1 什么是模板实例化? 1.2 实例化的触发条件 1.3 实例化的类型 二、隐式实例化 2.1 隐式实例化的工作原理 2.2 类模板的隐式实例化 2.3 隐式实例化的局限性 三、显式实例化 3.1 显式实例化声明(extern templat…...
TB开拓者策略交易信号闪烁根因及解决方法
TB开拓者策略信号闪烁分析 TB开拓者策略交易信号闪烁根因 TB开拓者策略交易信号闪烁根因分析 信号闪烁是交易策略开发中常见的问题,特别是在TB(TradeBlazer)开拓者等平台上。以下是信号闪烁的主要根因分析: 主要根因 未来函数问题 使用了包含未来信息…...

什么是RDMA?
什么是RDMA? RDMA(RemoteDirect Memory Access)技术全称远程直接内存访问,就是为了解决网络传输中服务器端数据处理的延迟而产生的。它将数据直接从一台计算机的内存传输到另一台计算机,无需双方操作系统的介入。这允许高吞吐、低延迟的网络…...