有道无术,术尚可求,有术无道,止于术。
本系列Jackson 版本 2.17.0
本系列Spring Boot 版本 3.2.4
源码地址:https://gitee.com/pearl-organization/study-jaskson-demo
文章目录
- 1. 前言
- 2. 起步依赖
- 3. 自动配置
- 3.1 JacksonProperties
- 3.2 JacksonAutoConfiguration
- 3.2.1 JacksonMixinConfiguration
- 3.2.2 JacksonObjectMapperBuilderConfiguration
- 3.2.3 JacksonObjectMapperConfiguration
- 3.2.4 ParameterNamesModuleConfiguration
- 3.2.5 Jackson2ObjectMapperBuilderCustomizerConfiguration
- 4. Jackson2ObjectMapperBuilderCustomizer
1. 前言
Spring Boot
是当前最流行的Java
应用开发框架,简化开发的同时也导致了很多开发人员只会写业务代码,并不太清楚内部组件和配置细节,一旦出问题或者需要性能优化时,就会显得无从下手。
所以推荐大家要多学习一下基础的应用框架,了解它们的详细用法和核心原理,不要太依赖于Spring Boot
的自动化。
接下来我们学习Spring Boot
是如何集成的Jackson
,并针对开发中常见的问题进行实战演示。
2. 起步依赖
Spring Boot
起步依赖(Starter Dependency
)机制,针对常见场景需要的依赖进行了统一打包处理,使用时只需要引入Starter
包即可。
例如针对JSON
应用场景,在Spring Boot
中提供了spring-boot-starter-json
启动器,默认引入的JSON
库是Jackson
:
dependencies {api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))api("org.springframework:spring-web")api("com.fasterxml.jackson.core:jackson-databind")api("com.fasterxml.jackson.datatype:jackson-datatype-jdk8")api("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")api("com.fasterxml.jackson.module:jackson-module-parameter-names")
}
除了jackson-databind
,还引入非核心模块jackson-datatype-jdk8
、jackson-datatype-jsr310
、jackson-module-parameter-names
,所以在Spring Boot
环境中,可以直接处理LocalDateTime
。
3. 自动配置
Spring Boot
基于约定大于配置思想,引入了Starter
包后,启动时扫描自动配置类,并自动装配声明的Bean
组件,开发者无需手动进行繁琐的配置,从而提高了开发效率,降低了维护成本。
spring-boot-autoconfigure
模块中包含了对Jackson
的自动配置:
3.1 JacksonProperties
Spring Boot
提供了配置属性类JacksonProperties
,方便我们直接在application.yml
配置文件中指定一些转换策略:
全部属性配置如下:
spring:jackson:constructor-detector: EXPLICIT_ONLY# 设置日志格式化格式,配置为日期格式字符串或完全限定的日期格式类名。例如 yyyy-MM-dd HH:mm:ssdate-format: yyyy-MM-dd HH:mm:ss# 宽松的全局默认设置default-leniency: true# 控制序列化期间包含的属性。使用 Jackson 的 JsonInclude.Include 枚举中的值之一进行配置。default-property-inclusion: always# 序列化配置 ,MAP 集合 , Map<SerializationFeature, Boolean>serialization:EAGER_SERIALIZER_FETCH: true# 反序列化特征,Map<DeserializationFeature, Boolean>deserialization:USE_BIG_DECIMAL_FOR_FLOATS: true# ObjectMapper/JsonMapper特征,Map<MapperFeature, Boolean>mapper:AUTO_DETECT_GETTERS: true# 生成器JsonGenerator.Feature,Map<com.fasterxml.jackson.core.JsonGenerator.Feature, Boolean>generator:AUTO_CLOSE_TARGET: true# 地区locale: zh_CN# 解析器 Map<Feature, Boolean># parser:# 设置属性命名策略,对应jackson下PropertyNamingStrategy中的常量值,SNAKE_CASE-返回的json驼峰式转下划线,json body下划线传到后端自动转驼峰式property-naming-strategy: SNAKE_CASE# 全局时区time-zone: GMT+8# 可见性阈值,可用于限制自动检测哪些方法(和字段)。visibility:GETTER: ANY
3.2 JacksonAutoConfiguration
Spring Boot
提供了自动配置类JacksonAutoConfiguration
,包含了多个内部配置类:
在自动配置类的static
块中,配置了两个默认特征,设置序列化日志时间不使用时间戳,并注册JsonComponentModule Bean
对象,用于注册所有@JsonComponent
标识的Bean
:
@AutoConfiguration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {@Beanpublic JsonComponentModule jsonComponentModule() {return new JsonComponentModule();}private static final Map<?, Boolean> FEATURE_DEFAULTS;static {Map<Object, Boolean> featureDefaults = new HashMap();featureDefaults.put(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);featureDefaults.put(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);FEATURE_DEFAULTS = Collections.unmodifiableMap(featureDefaults);}// 省略内部配置类
3.2.1 JacksonMixinConfiguration
内部自动配置类JacksonMixinConfiguration
用于扫描@JsonMixin
标识的类并注册,以支持混合注解:
@Configuration(proxyBeanMethods = false)static class JacksonMixinConfiguration {@Beanstatic JsonMixinModuleEntries jsonMixinModuleEntries(ApplicationContext context) {List<String> packages = AutoConfigurationPackages.has(context) ? AutoConfigurationPackages.get(context): Collections.emptyList();return JsonMixinModuleEntries.scan(context, packages);}@BeanJsonMixinModule jsonMixinModule(ApplicationContext context, JsonMixinModuleEntries entries) {JsonMixinModule jsonMixinModule = new JsonMixinModule();jsonMixinModule.registerEntries(entries, context.getClassLoader());return jsonMixinModule;}}
3.2.2 JacksonObjectMapperBuilderConfiguration
内部自动配置类JacksonObjectMapperBuilderConfiguration
注册了一个多例的Jackson2ObjectMapperBuilder
(用于构建ObjectMapper
对象),并调用所有的定制器Jackson2ObjectMapperBuilderCustomizer
进行定制化处理:
@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)static class JacksonObjectMapperBuilderConfiguration {@Bean@Scope("prototype")@ConditionalOnMissingBeanJackson2ObjectMapperBuilder jacksonObjectMapperBuilder(ApplicationContext applicationContext,List<Jackson2ObjectMapperBuilderCustomizer> customizers) {Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();builder.applicationContext(applicationContext);customize(builder, customizers);return builder;}private void customize(Jackson2ObjectMapperBuilder builder,List<Jackson2ObjectMapperBuilderCustomizer> customizers) {for (Jackson2ObjectMapperBuilderCustomizer customizer : customizers) {customizer.customize(builder);}}}
3.2.3 JacksonObjectMapperConfiguration
内部自动配置类JacksonObjectMapperConfiguration
注册了一个单例的ObjectMapper Bean
对象到容器中,是使用容器中的Jackson2ObjectMapperBuilder
构建的,并且是线程安全的,所以在使用时直接使用@Autowired
注入该实例即可。
@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)static class JacksonObjectMapperConfiguration {@Bean@Primary // 主要的@ConditionalOnMissingBean // 在应用程序没有注册ObjectMapper时生效ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {return builder.createXmlMapper(false).build();}}
3.2.4 ParameterNamesModuleConfiguration
内部自动配置类ParameterNamesModuleConfiguration
用于注册了ParameterNamesModule
:
@Configuration(proxyBeanMethods = false)@ConditionalOnClass(ParameterNamesModule.class)static class ParameterNamesModuleConfiguration {@Bean@ConditionalOnMissingBeanParameterNamesModule parameterNamesModule() {return new ParameterNamesModule(JsonCreator.Mode.DEFAULT);}}
3.2.5 Jackson2ObjectMapperBuilderCustomizerConfiguration
内部自动配置类Jackson2ObjectMapperBuilderCustomizerConfiguration
的主要作用是将JacksonProperties
、Module
中的配置,集成到应用环境中。
注册了一个StandardJackson2ObjectMapperBuilderCustomizer
:
StandardJackson2ObjectMapperBuilderCustomizer
实现了Jackson2ObjectMapperBuilderCustomizer
,所以在自动注册Jackson2ObjectMapperBuilder
时,会调用customize
方法,将JacksonProperties
的配置项都集成到Jackson2ObjectMapperBuilder
中:
4. Jackson2ObjectMapperBuilderCustomizer
Jackson2ObjectMapperBuilderCustomizer
定制器接口,用于对Jackson2ObjectMapperBuilder
的构建行为进行定制:
@FunctionalInterface
public interface Jackson2ObjectMapperBuilderCustomizer {void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder);}
他们之间的关系如下所示:
在实际开发中,可以注册Jackson2ObjectMapperBuilderCustomizer
来配置ObjectMapper
:
@Beanpublic Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {return builder -> {builder.serializerByType(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);builder.deserializerByType(Long.class,com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);};}