消息转换器--通过此工具进行时间转换
在 Spring MVC 处理中,HttpMessageConverter
负责在 HTTP 报文与 Java 对象之间完成序列化/反序列化。
项目常见需求包括:统一 JSON 日期格式、过滤未知字段、为前端与后端提供一致的时间序列化策略等。
下文以截图中的代码为例说明 如何编写并注册自定义 JSON 消息转换器,并给出关键原理与最小可运行配置。
1 HttpMessageConverter
的职责与执行流程
要点 | 说明 | 参考 |
---|---|---|
转换时机 | Spring MVC 在解析 @RequestBody 或生成 @ResponseBody 时,通过 HttpMessageConverter 完成 Java ↔ JSON/XML 映射Baeldung | turn0search0 |
选择规则 | Spring 按 注册顺序 遍历转换器:第 1 个声明“我能处理当前媒体类型”即被选中,后续不再尝试Home | turn0search9 |
默认实现 | Spring Boot 自动装配了多种实现,JSON 部分由 MappingJackson2HttpMessageConverter 配合全局 ObjectMapper 完成Medium | turn0search8 |
2 为何需要自定义 JSON 转换器
-
Java 8 日期(
LocalDateTime/LocalDate/LocalTime
)默认序列化为 ISO-8601,如2023-05-26T14:45:30
。 -
业务常见格式为
yyyy-MM-dd HH:mm
等,需要统一输出/输入格式并容忍未知字段。 -
通过自定义
ObjectMapper
并置于 首位,即可在不修改实体类的情况下实现全局控制Stack OverflowBaeldung。
3 代码拆解:extendMessageConverters
java
复制编辑
@Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // ① 构造 JSON 消息转换器 MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); // ② 注入自定义 ObjectMapper converter.setObjectMapper(new JacksonObjectMapper()); // ③ 插入 converters 第 0 位,确保优先匹配 converters.add(0, converter); }
步骤 | 作用 |
---|---|
① | 创建基于 Jackson 的 JSON 转换器Java Code Geeks |
② | 替换默认 ObjectMapper ,实现专用序列化策略 |
③ | 将转换器置于索引 0,确保 Spring 首先选择该实现Stack Overflow |
4 自定义 JacksonObjectMapper
的关键设置
java
复制编辑
public class JacksonObjectMapper extends ObjectMapper { public static final String DATE_TIME_FMT = "yyyy-MM-dd HH:mm"; public static final String DATE_FMT = "yyyy-MM-dd"; public static final String TIME_FMT = "HH:mm:ss"; public JacksonObjectMapper() { // 1. 关闭未知字段失败 this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 2. 注册自定义 (de)serializer SimpleModule module = new SimpleModule() .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FMT))) .addSerializer (LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FMT))) .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FMT))) .addSerializer (LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FMT))) .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_FMT))) .addSerializer (LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_FMT))); this.registerModule(module); } }
-
日期格式统一:通过
LocalDateTimeSerializer/Deserializer
指定业务格式Stack Overflow。 -
容错设置:
FAIL_ON_UNKNOWN_PROPERTIES=false
避免前端字段冗余时抛异常Baeldung。
5 完整序列化流程示例
-
请求阶段
-
前端发送 JSON:
{"orderTime":"2023-11-01 12:30"}
。 -
自定义转换器 → 反序列化为
LocalDateTime
对象,格式解析成功。
-
-
响应阶段
-
Controller 返回含时间字段的实体。
-
同一转换器序列化 → JSON 输出
"2023-11-01 12:30"
而非 ISO-8601。
-
-
顺序保证
-
若未在索引 0 插入,Spring 可能使用默认转换器,日期仍为
2023-11-01T12:30:00
Stack Overflow。
-
6 实践注意事项
问题 | 建议 |
---|---|
多模块扫描 | 若存在非业务 Controller,需调整 basePackage() ,避免生成冗余接口文档。 |
与 Spring Boot 2.6+ | 当引入 Spring MVC + Spring Boot 2.6+ 时,Springfox 可能不兼容;可升级至 springdoc-openapi + Knife4j 3.x。 |
性能 | 自定义序列化器无需每次创建,可通过单例 ObjectMapper 复用。 |