spring boot 属性加载顺序
- 默认属性(通过
SpringApplication.setDefaultProperties设置) @Configuration配置类通过@PropertySource启用的资源文件- 配置文件
RandomValuePropertySource- 操作系统属性
System.getProperties()- JNDI属性(
java:comp/env) ServletContext初始化参数ServletConfig初始化参数SPRING_APPLICATION_JSON- 命令行参数
- 单元测试时
@SpringBootTest配置的属性 - 单元测试时
@TestPropertySource启用的属性 - devtools使用的
$HOME/.config/spring-boot目录下的文件
spring boot 配置文件加载顺序
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.external-config.files
spring boot默认会按照以下顺序, 在下面的文件夹中查找配置文件(优先级由低到高):
- classpath根目录
- classpath下的
/config文件夹 - 启动目录
- 启动目录下的
/config文件夹 - 启动目录下的
/config文件夹的子文件夹
启动目录指的是你在哪个目录下启动的应用, 举例来说: 应用包
user-center-1.0.0.jar在/home/test/app/下如果在
/home/test/app/下执行java -jar user-center-1.0.0.jar, 那么启动目录就是/home/test/app/如果在
/home/test/下执行java -jar app/user-center-1.0.0.jar, 那么启动目录就是/home/test/
classpath可以简单理解为应用的
resource目录
spring可以通过命令行参数spring.config.location自定义配置文件加载顺序, 如: java -Dspring.config.location=classpath:/properties/,file:./properties/ -jar user-center-1.0.0.jar, spring会完全按照这个配置进行查找, 配置文件加载顺序会变成下面这样:
file:./properties/classpath:properties/
另外, spring还可以通过命令行参数spring.config.additional-location指定额外的配置文件路径, 如: java -Dspring.config.additional-location=classpath:/custom-config/,file:./custom-config/ -jar user-center-1.0.0.jar, 那么配置文件加载顺序就变成了:
file:./custom-config/classpath:custom-config/file:./config/file:./classpath:/config/classpath:/
需要注意的是, 如果一个配置项在多个文件都定义了, 则先定义的优先级更高, 所以应用resource下的配置文件优先级最高
profile配置文件加载
spring中可以使用application-{profile}.properties配置作为application.properties配置的补充, 如果没有配置要激活的profile, 则spring会加载application-default.properties配置文件.
指定application-{profile}.properties的优先级高于application.properties, 而且如果激活了多个profile, 则后面的profile会覆盖前者, 这条规则比上面文件目录规则优先级更高, 比如java -jar -Dspring.profiles.active=prod user-center-1.0.0jar启动应用. 结合目录加载顺序, 一个配置项的优先级如下:
file:./config/spring-prod.propertiesfile:./spring-prod.propertiesclasspath:/config/spring-prod.propertiesclasspath:spring-prod.propertiesfile:./config/spring.propertiesfile:./spring.propertiesclasspath:/config/spring.propertiesclasspath:spring.properties
profile优先级最高, 其次先外部再内部, 然后config目录, 最后是默认配置
配置参数加载顺序
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config
spring中通过${xxx}加载变量时, 会从多个位置查找这个配置项, 具体顺序如下(不完整, 只保留运行时需要关心的):
- 命令行
ServletConfig初始化参数ServletContext初始化参数System.getProperties()- 操作系统环境变量
- 外部目录下的
application-{profile}.properties文件 classpath下的application-{profile}.properties文件- 外部目录的
application.properties classpath下的application.properties文件- 应用内使用
@PropertySource的配置类(@Configuration)
序列化LocalDateTime成数组问题
问题表现
在JDK8之前, 后端如果想将日期格式的JSON数据转成时间戳返回给前端, 只需要在配置文件中增加如下配置
1 | # 返回时间戳 |
使用@responseBody返回json数据时,会自动将时间格式化为毫秒值。
但是在使用了LocalDateTime后, 返回的数据格式成了这样"createTime":[2020,6,9,15,47,29], 上面的配置没有失效了. 对此官方文档的说明如下: jackson-modules-java8
LocalDate,LocalTime,LocalDateTime, andOffsetTime, which cannot portably be converted to timestamps and are instead represented as arrays whenWRITE_DATES_AS_TIMESTAMPSis enabled.
解决办法
自定义
JsonSerialize1
2
3
4
5
6
7public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> {
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli());
}
}在实体类时间属性上,加入
@JsonSerialize(using = LocalDateTimeConverter.class)注解即可