[已解决] Spring MVC 消息转换器全攻略:日期格式化、Long 精度丢失一网打尽
本文聚焦“苍穹外卖”开发中 Long 类型精度丢失与日期格式不统一两大痛点,深入解析了 HttpMessageConverter 的核心作用与配置实战。文章指出,转换器是 Spring MVC 处理 @RequestBody 与 @ResponseBody 的“翻译官”。通过自定义 JacksonObjectMapper 并重写 extendMessageConverters 方法,可实现 Lon
💻 痛点导入:消失的精度与奇怪的日期
深夜 11 点,你还在调试“苍穹外卖”的订单模块。 “明明后端传过去的 ID 是 17283940582736451,怎么前端一接收就变成了 17283940582736450?还有这日期,为什么返回的是一串数字时间戳,而不是 yyyy-MM-dd HH:mm:ss?”
你揉了揉发涩的眼睛,翻遍了 Controller 也没找到问题。其实,这一切的背后,都是 Spring MVC 消息转换器在“搞鬼”。
如果你也正被 JSON 序列化、日期格式、字段空值转换等问题折磨,这篇文章就是你的救命稻草。
🛠️ 一、 什么是 HttpMessageConverter?(快速入门)
在 Spring MVC 中,当我们在 Controller 方法上使用 @RequestBody 或 @ResponseBody 时,Spring 就会自动调用 HttpMessageConverter。
核心结论: 它是 Spring MVC 提供的用于处理 HTTP 请求和响应消息的转换接口。它负责将请求体中的 JSON/XML 转换为 Java 对象,或将 Java 对象序列化为响应体。
1.1 常见实现类
Spring 默认内置了多个转换器,最常用的莫过于:
- StringHttpMessageConverter:处理字符串。
- MappingJackson2HttpMessageConverter:利用 Jackson 处理 JSON(这是我们最常打交道的一个)。
🚀 二、 实战演练:在“苍穹外卖”中统一配置转换器
在项目中,我们通常需要自定义一个 JacksonObjectMapper 来解决日期格式化和 Long 类型精度丢失(JS 不支持 64 位整数)的问题。
2.1 第一步:定义对象映射器
public class JacksonObjectMapper extends ObjectMapper {
public JacksonObjectMapper() {
super();
// 收到未知属性时不报错
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
// 定义日期、长整型的序列化规则
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
simpleModule.addSerializer(Long.class, ToStringSerializer.instance); // 重点:解决 Long 精度丢失
this.registerModule(simpleModule);
}
}
2.2 第二步:在配置类中扩展转换器
我们需要在继承了 WebMvcConfigurationSupport 的配置类中重写 extendMessageConverters 方法。
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/**
* 扩展 Spring MVC 框架的消息转换器
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 1. 创建一个新的消息转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
// 2. 为消息转换器设置一个对象转换器(即上面的 JacksonObjectMapper)
converter.setObjectMapper(new JacksonObjectMapper());
// 3. 将自己的转换器添加到容器中,并设置为第一优先级
converters.add(0, converter);
}
}
🧠 三、 深度剖析:转换器的工作原理
3.1 核心流程图

3.2 为什么用 extendMessageConverters 而不是 configureMessageConverters?
- configureMessageConverters:会覆盖掉 Spring 默认的所有转换器。如果你只想加一个,剩下的就得手动全部重配,非常麻烦。
- extendMessageConverters:是在默认转换器列表的末尾追加。通过 converters.add(0, converter),我们可以把自定义的转换器放在首位,确保它优先被匹配。
📊 四、 常见避坑场景对比

💡 五、 面试加分项:内容协商机制
面试官:Spring MVC 是如何决定使用哪个 MessageConverter 的?
回答要点:
- Content-Type:根据请求头中的 Content-Type(如 application/json)匹配 canRead。
- Accept:根据请求头中的 Accept(如 application/xml)匹配 canWrite。
- 返回值类型:根据 Controller 方法的返回类型,判断转换器是否支持处理该类。
- 优先级:遍历 converters 列表,第一个匹配成功的转换器将承担重任。
✅ 总结与互动
Spring MVC 消息转换器是解决前后端“沟通障碍”的翻译官。通过自定义转换器,我们不仅能统一接口规范,还能避开 JS 处理大数的陷阱。
每日一思: 如果你的项目既要支持 JSON 也要支持 XML,你应该如何配置转换器?欢迎在评论区分享你的配置方案!👇
看完有收获?别忘了点赞、关注、收藏“三连”哦!你的支持是我更新的最大动力!🌟
更多推荐



所有评论(0)