Spring boot 配置文件场景分析
默认情况下如果将spring boot项目,打包成一个fat jar,基本不存在读取外在配置文件的问题,因为 src/main/resources/的yaml或者properties文件,都会打进 jar 内。那如果我们想读取jar外的配置文件该如何做呢?
Spring boot 配置文件优先级
(1) 打包后的 Jar 包以外的 application-.properties;
(2) 打包后的 Jar 包以外的 application.properties;
(3) Jar 包内部的 application-.properties;
(4) Jar 包内部的 application.properties。
可以看到 Jar 包外部的文件比内部的优先级高,特定 Profile 的文件比公共的文件优先级高
指定 profile + 读取外部配置文件
1,当前目录的 /config 子目录;
2,当前目录;
3,CLASSPATH 中的 /config 目录;
4,CLASSPATH 根目录。
也就是说,如果要读取任何外部文件,不需要额外加任何参数,只需要在jar同级目录下,新建一个config目录,然后把配置文件放进去即可,这样spring boot读取到后,会自动将其中的内容添加到 Spring 的 Environment 中。
如果搭配上指定profile的方式,就可以在存在多份profile的前提下,实现精确读取外部配置文件:
#方法一: 如下参数顺序无关
java -jar -Dspring.profiles.active=test xxx.jar
java -Dspring.profiles.active=test -jar xxx.jar
#方法二: 或使用环境变量
export SPRING_PROFILES_ACTIVE=test
java -jar xxx.jar
改变主配置文件名
默认情况下,主配置文件名为 [ application 或 application- ],但如果你想改变这个值,也可以的,可以使用如下方式:
java -jar foo.jar --spring.config.name=spring
这样的话,你的 jar 同级目录下,可以存在多个以 spring 开头的 profile ,如下:
spring-dev.yaml
spring-test.yaml
spring-prod.yaml
改变默认配置加载路径
大多时候,知道了上面的几种使用方法后,基本解决 90% 的配置加载问题了,但有些时候,你不想使用spring boot 默认的配置文件加载优先级,该怎么办呢?
spring.config.location
参数用于指定查找配置文件的路径,默认是下面这样的,用逗号分隔,越靠后的优先级越高:
classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/
spring.config.location可以指定文件,也可以指定目录,指定目录时候必须以反斜杠结尾代表是目录:如下使用方式:
# 使用指定目录
java -Dspring.profiles.active=test -jar comet-service/target/comet-service-0.1-SNAPSHOT.jar --spring.config.location=/tmp/
# 使用 optional,当目录路径不存在时不报错
java -Dspring.profiles.active=test -jar comet-service/target/comet-service-0.1-SNAPSHOT.jar --spring.config.location=optional:/tmp/
# 使用指定文件
java -Dspring.profiles.active=test -jar comet-service/target/comet-service-0.1-SNAPSHOT.jar --spring.config.location=/tmp/application-prod.yaml
# 使用 optional,当文件路径不存在时不报错
java -Dspring.profiles.active=test -jar comet-service/target/comet-service-0.1-SNAPSHOT.jar --spring.config.location=optional:/tmp/application-prod.yaml
spring.config.additional-location
spring.config.additional-location 配置项和 spring.config.location 的区别在于:
- 这个属性用于指定除了主配置文件之外的附加配置文件位置。
- 它允许应用程序加载额外的配置文件,这些文件不会覆盖主配置文件中的设置,而是作为补充。
- 这可以用于将特定环境的配置与通用配置分开,或者在不重新打包应用程序的情况下动态地添加配置。
- 与spring.config.location一样,spring.config.additional-location也可以是文件系统路径或类路径下的资源。
例如:
java -jar myapp.jar --spring.config.location=classpath:/default-config.yml --spring.config.additional-location=file:./dev-config.yml
在这个例子中,/default-config.yml是主配置文件,而./dev-config.yml是开发环境的附加配置文件。
容器化场景下最佳实践
现在很多公司都上了 Kubernetes 进行资源管理和容器编排,云原生和容器化部署是大势所趋,最后我带你看下 Spring boot 如何结合 Docker 和 Kubernetes 使用外部配置文件,例子Dockerfile如下:
FROM openjdk
# 定义环境变量,可以dockefile 构建时覆盖
ARG BUILD_ENV=dev
# 定义打包后的 jar 名,注意用 * 号统配版本
ARG JAR_NAME=comet-service-*-SNAPSHOT.jar
# 将 ARG 参数赋值给环境变量
ENV ENV_JAR_NAME=${JAR_NAME}
ENV SPRING_PROFILES_ACTIVE=${BUILD_ENV}
# 添加编译后的jar,到容器内目录
ADD ./comet-service/target/${ENV_JAR_NAME} /opt/
# 注意文件添加到某个目录,目录后需要带 /
ADD ./build/application-test.yaml /opt/config/
# 设置工作目录
WORKDIR /opt/
# 启动命令
ENTRYPOINT java -jar ${ENV_JAR_NAME}
# 端口暴漏
EXPOSE 7878
# 构建
# docker build --progress plain -t comet:v1 -f ./build/Dockerfile .
# 调试
# docker run -it --entrypoint bash -v /tmp/:/tmp comet:v1
如上一个 dockerfile 构建的镜像,如果想要指定 profile + 读取外置 profile 应该怎么做 ?
很简单,有很多种方法,这里介绍两种最简单的:
(1)构建时添加 外部文件到 jar 的同级目录 /opt/config 下或者 run 的时候动态挂载(更灵活)
(2)在 kubernetes 中挂载文件到 /opt/config 下
然后,如果纯 docker 启动:
# 如果构建时没有添加文件,就挂载目录加指定环境变量
docker run -it -p 7878:7878 -e SPRING_PROFILES_ACTIVE=aone -v /tmp/:/opt/config comet:v1
如果使用 kubernetes 启动:
1,使用 configmap 挂载文件到指定目录
2,注入 env 变量即可
参考文档
Externalized Configuration :: Spring Boot
版权归原作者 三劫散仙 所有, 如有侵权,请联系我们删除。