Jackson 2.x 系列【25】Spring Boot 集成之起步依赖、自动配置

有道无术,术尚可求,有术无道,止于术。

本系列Jackson 版本 2.17.0

本系列Spring Boot 版本 3.2.4

源码地址:https://gitee.com/pearl-organization/study-jaskson-demo

文章目录

    • [1. 前言](#1. 前言)
    • [2. 起步依赖](#2. 起步依赖)
    • [3. 自动配置](#3. 自动配置)
      • [3.1 JacksonProperties](#3.1 JacksonProperties)
      • [3.2 JacksonAutoConfiguration](#3.2 JacksonAutoConfiguration)
        • [3.2.1 JacksonMixinConfiguration](#3.2.1 JacksonMixinConfiguration)
        • [3.2.2 JacksonObjectMapperBuilderConfiguration](#3.2.2 JacksonObjectMapperBuilderConfiguration)
        • [3.2.3 JacksonObjectMapperConfiguration](#3.2.3 JacksonObjectMapperConfiguration)
        • [3.2.4 ParameterNamesModuleConfiguration](#3.2.4 ParameterNamesModuleConfiguration)
        • [3.2.5 Jackson2ObjectMapperBuilderCustomizerConfiguration](#3.2.5 Jackson2ObjectMapperBuilderCustomizerConfiguration)
    • [4. Jackson2ObjectMapperBuilderCustomizer](#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

java 复制代码
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-jdk8jackson-datatype-jsr310jackson-module-parameter-names,所以在Spring Boot环境中,可以直接处理LocalDateTime

3. 自动配置

Spring Boot基于约定大于配置思想,引入了Starter包后,启动时扫描自动配置类,并自动装配声明的Bean组件,开发者无需手动进行繁琐的配置,从而提高了开发效率,降低了维护成本。

spring-boot-autoconfigure模块中包含了对Jackson的自动配置:

3.1 JacksonProperties

Spring Boot 提供了配置属性类JacksonProperties,方便我们直接在application.yml配置文件中指定一些转换策略:

全部属性配置如下:

yml 复制代码
spring:
  jackson:
    constructor-detector: EXPLICIT_ONLY
    # 设置日志格式化格式,配置为日期格式字符串或完全限定的日期格式类名。例如 yyyy-MM-dd HH:mm:ss
    date-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

java 复制代码
@AutoConfiguration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {

    @Bean
    public 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标识的类并注册,以支持混合注解:

java 复制代码
	@Configuration(proxyBeanMethods = false)
	static class JacksonMixinConfiguration {
		@Bean
		static JsonMixinModuleEntries jsonMixinModuleEntries(ApplicationContext context) {
			List<String> packages = AutoConfigurationPackages.has(context) ? AutoConfigurationPackages.get(context)
					: Collections.emptyList();
			return JsonMixinModuleEntries.scan(context, packages);
		}
		@Bean
		JsonMixinModule jsonMixinModule(ApplicationContext context, JsonMixinModuleEntries entries) {
			JsonMixinModule jsonMixinModule = new JsonMixinModule();
			jsonMixinModule.registerEntries(entries, context.getClassLoader());
			return jsonMixinModule;
		}
	}
3.2.2 JacksonObjectMapperBuilderConfiguration

内部自动配置类JacksonObjectMapperBuilderConfiguration 注册了一个多例的Jackson2ObjectMapperBuilder(用于构建ObjectMapper对象),并调用所有的定制器Jackson2ObjectMapperBuilderCustomizer进行定制化处理:

java 复制代码
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)
	static class JacksonObjectMapperBuilderConfiguration {

		@Bean
		@Scope("prototype")
		@ConditionalOnMissingBean
		Jackson2ObjectMapperBuilder 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注入该实例即可。

java 复制代码
	@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

java 复制代码
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(ParameterNamesModule.class)
	static class ParameterNamesModuleConfiguration {

		@Bean
		@ConditionalOnMissingBean
		ParameterNamesModule parameterNamesModule() {
			return new ParameterNamesModule(JsonCreator.Mode.DEFAULT);
		}

	}
3.2.5 Jackson2ObjectMapperBuilderCustomizerConfiguration

内部自动配置类Jackson2ObjectMapperBuilderCustomizerConfiguration的主要作用是将JacksonPropertiesModule中的配置,集成到应用环境中。

注册了一个StandardJackson2ObjectMapperBuilderCustomizer

StandardJackson2ObjectMapperBuilderCustomizer实现了Jackson2ObjectMapperBuilderCustomizer,所以在自动注册Jackson2ObjectMapperBuilder时,会调用customize方法,将JacksonProperties的配置项都集成到Jackson2ObjectMapperBuilder中:

4. Jackson2ObjectMapperBuilderCustomizer

Jackson2ObjectMapperBuilderCustomizer定制器接口,用于对Jackson2ObjectMapperBuilder的构建行为进行定制:

java 复制代码
@FunctionalInterface
public interface Jackson2ObjectMapperBuilderCustomizer {

	void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder);

}

他们之间的关系如下所示:

在实际开发中,可以注册Jackson2ObjectMapperBuilderCustomizer来配置ObjectMapper

java 复制代码
    @Bean
    public 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);
        };
    }
相关推荐
Wang153012 小时前
js核心概念
json
jameslogo14 小时前
如何用RocketMQTemplate发送事务消息
java·spring boot·rocketmq
无关868816 小时前
Spring Boot 项目标准化部署打包实战
java·spring boot·后端
jay神16 小时前
基于微信小程序课外创新实践学分认定系统
java·spring boot·小程序·vue·毕业设计
阿丰资源17 小时前
基于Spring Boot的酒店客房管理系统
java·spring boot·后端
zzqssliu17 小时前
SpringBoot框架搭建跨境独立站|Taocarts代购系统订单模块深度开发
java·spring boot·后端
武子康17 小时前
Java-219 RocketMQ Spring Boot 集成指南:生产者与消费者实战
java·spring boot·分布式·kafka·消息队列·rocketmq·java-rocketmq
想学习java初学者18 小时前
SpringBoot整合GS1编码解码
java·spring boot·后端
i220818 Faiz Ul19 小时前
智慧养老平台|基于SprinBoot+vue的智慧养老平台系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·智慧养老平台