Jackson2ObjectMapperBuilderCustomizer配置集成SpringCloud时不生效
Spring Cloud环境下Jackson日期格式自定义配置不生效根因说明
问题涉及的自定义配置
目标是通过如下配置自定义Java 8中LocalDateTime、LocalDate、LocalTime类型的序列化与反序列化日期格式:
@Bean @Primary public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { return builder -> { builder.simpleDateFormat(dateTimeFormat) .serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))) .deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat))) .serializerByType(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))) .deserializerByType(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat))) .serializerByType(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(timeFormat))) .deserializerByType(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(timeFormat))); }; }
环境信息:Spring Boot版本为2.6.9,上述配置在未集成Feign、Eureka等Spring Cloud组件的普通Spring Boot项目中可正常生效,集成Spring Cloud组件后配置不生效,异常现象如下:
两个项目均通过添加@EnableWebMvc注解、实现WebMvcConfigurer接口的方式配置拦截器,相关配置代码如下:
@Configuration @EnableWebMvc public class WebConfiguration implements WebMvcConfigurer {
最终通过重写extendMessageConverters方法手动调整HttpMessageConverter列表的方式解决了问题,实现代码如下:
@Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); converters.add(0, mappingJackson2HttpMessageConverter); }
配置不生效的根本原因
问题由两层配置逻辑叠加导致:
@EnableWebMvc会中断Spring Boot默认的Jackson自动装配链路
Spring Boot默认的JacksonAutoConfiguration逻辑会自动收集容器中所有Jackson2ObjectMapperBuilderCustomizer实例,统一应用到全局ObjectMapper构造流程中,供Web层的Jackson消息转换器使用。一旦类路径上存在加了@EnableWebMvc的配置类,Spring Boot会放弃Web层的Jackson自动配置,改用Spring MVC原生的消息转换器初始化逻辑,这套原生逻辑不会主动收集和应用自定义的Customizer。普通Spring Boot项目中没有额外组件提前创建Jackson转换器,所以即使加了@EnableWebMvc,后续初始化转换器时仍能从上下文拿到通过Customizer定制的Builder,配置不会失效。- Spring Cloud OpenFeign会提前创建未应用自定义规则的Jackson转换器
Feign组件启动时会为自身的RPC编解码逻辑提前创建独立的MappingJackson2HttpMessageConverter实例,这个实例构造时不会加载容器中的Jackson2ObjectMapperBuilderCustomizer,默认使用Jackson原生的时间序列化规则。当Spring MVC初始化消息转换器列表时,会把Feign提前创建的这个未定制的转换器加入列表,且排序优先级高于后续创建的、应用了自定义规则的转换器,接口序列化时优先匹配到这个不符合预期的转换器,就会出现日期格式不生效的问题。
手动修复方案的生效逻辑
在extendMessageConverters中移除了所有已存在的MappingJackson2HttpMessageConverter实例,再把提前配置好、应用了自定义日期规则的Jackson转换器放到列表首位,接口处理时会优先匹配到这个正确配置的转换器,因此格式恢复正常。
更轻量的替代修复方案
- 移除Web配置类上的
@EnableWebMvc注解:仅实现WebMvcConfigurer接口添加拦截器不会触发Spring MVC全量接管,Spring Boot的Jackson自动配置链路可以正常工作,Customizer配置会自动应用到所有Jackson转换器实例,包括Feign使用的转换器。 - 如果必须保留
@EnableWebMvc,直接声明@Primary标记的MappingJackson2HttpMessageConverterBean,在构造Bean时直接设置好时间序列化规则,不用依赖Customizer的自动装配逻辑。 - 单独给Feign指定和Web层一致的ObjectMapper实例,避免两套Jackson配置规则不一致。
内容的提问来源于stack exchange,提问作者Mr Lou
相关产品推荐
相关产品推荐

