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.properties
file:./spring-prod.properties
classpath:/config/spring-prod.properties
classpath:spring-prod.properties
file:./config/spring.properties
file:./spring.properties
classpath:/config/spring.properties
classpath: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_TIMESTAMPS
is enabled.
解决办法
自定义
JsonSerialize
1
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)
注解即可