1. 为什么说直接注入ObjectMapper是个“坑”?
我猜很多刚开始用SpringBoot做Web开发的朋友,都踩过这个坑:项目里日期格式不对,或者前端传过来的空字符串想自动转成null,于是上网一搜,解决方案清一色是“自己定义一个ObjectMapper的@Bean”。代码一写,配置一加,本地一跑,诶,问题解决了!心里美滋滋。结果等到项目上了测试环境,或者和其他模块一集成,发现别的接口突然报错了,或者一些原本好好的全局配置(比如统一的时间格式)失效了。这时候排查起来,那叫一个头疼。
这个问题的根源,就在于你直接向Spring容器注入了一个全新的ObjectMapper实例。在SpringBoot的世界里,ObjectMapper是一个“明星”组件,很多内部功能(比如@RestController的JSON转换、@JsonView的支持、甚至一些Starter的自动配置)都依赖于它。SpringBoot在启动时,会通过JacksonAutoConfiguration等自动配置类,精心准备一个功能齐全的ObjectMapper,并把它注册到容器里。这个默认的ObjectMapper已经预先配置好了很多合理的默认行为,比如标准的日期格式处理、空值处理策略等等。
当你自己写一个@Bean方法返回一个新的ObjectMapper时,就相当于告诉Spring:“嘿,别用你那个了,用我这个!” Spring会非常“听话”地用你的这个Bean覆盖掉它自己创建的那个。问题来了:你的ObjectMapper很可能只配置了你关心的那一两个特性(比如日期格式),而把SpringBoot默认配置的其他几十项优秀设定都给丢掉了。这就好比为了给房间装个新窗帘,结果把整面墙都拆了重砌,风险可想而知。
我亲身经历过一次,当时为了给Long类型序列化成字符串(防止前端JavaScript精度丢失),就自己注入了ObjectMapper。结果项目里用到的@JsonFormat注解全部失效,日志里各种日期解析异常,查了半天才定位到这个原因。所以,在SpringBoot2环境下,直接注入ObjectMapper @Bean是下策,是破坏性的覆盖,而不是建设性的增强。
那么,正确的“优雅”姿势是什么?答案就是利用SpringBoot为我们准备好的扩展点:Jackson2ObjectMapperBuilderCustomizer接口。它的设计理念非常巧妙——不是让你去替换整个“汽车发动机”(ObjectMapper),而是让你去提供一套“个性化改装套件”(Customizer),由SpringBoot的装配流水线(Jackson2ObjectMapperBuilder)在组装发动机时,自动把你的套件给加上去。这样,你既能享受到原厂发动机的所有优良性能,又能加上你想要的定制化功能。
2. 认识核心武器:Jackson2ObjectMapperBuilderCustomizer
光说概念可能有点抽象,咱们直接上代码,看看这个接口到底长啥样,怎么用。其实它简单得惊人:
@FunctionalInterface
public interface Jackson2ObjectMapperBuilderCustomizer {
void customize(Jackson2ObjectMapperBuilder builder);
}
对,就一个方法!你的任务就是实现这个customize方法,然后通过builder对象来“告诉”SpringBoot你想怎么调整ObjectMapper的配置。Jackson2ObjectMapperBuilder这个类可以理解为一个功能强大的配置工具,它提供了大量便捷的方法来设置序列化器、反序列化器、日期格式、特性开关等等。
怎么让它生效呢?最简单的方式,就是让你的配置类实现这个接口,并加上@Configuration注解,这样SpringBoot在启动时就会自动发现并应用它。下面是一个最基础的架子:
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilder

1974

被折叠的 条评论
为什么被折叠?



