Properties-and-Configuration
在学习Properties和Configuration之前,我们先要熟悉spring框架。可以从springinitialzr拉一个框架来观察。这里建议在跟教程的时候多写几个简单的项目,这样框架就会自然而然熟悉起来。
这里我把maven编译的spring项目架构画了在这里。
springboot 项目架构
1 | demo |
在熟悉框架之后进入我们的学习,这次学习的内容是guide中的Properties and Configuration ,觉得看完这篇blog还不是很清楚的可以看下原文.
原文链接:https://docs.spring.io/spring-boot/how-to/properties-and-configuration.html
接下来会从6个部分讲解properties和configuration是如何被spring 使用的。
part1: maven资源展开(限制条件:生产环境即源码 main 中,test 中不行)
资源过滤
在 application.yml / properties 中,常用
@ @占位符来避免硬编码,是从已解析的pom.xml中找到占位键对应的值,进行替换后写入target / classes中的application.yml。例如在 src 中 application.properties 中写version = @project.version@替换。展开属性,也就是占位符的替换,是由 maven 在编译、打包期间进行的。
maven-resources-plugin是执行者,这个插件是pom.xml<parent>中配置spring-boot-starter就自带的。常在pom.xml中<parent>自带的。Tips:如果不用
starter-parent需要在prom.xml中添加和 相关内容 展开属性失效:当开启
addResources标识的时候,开启addResources的同时,也开启了热重载(hot reloading),将src/main/resources挂载到运行的 classpath 上
TIP:这里的挂载是什么?有什么效果?
正常(非挂载状态下),Java 程序运行只能读取target / classes(即编译后的目录)中的文件,如果在程序运行时修改源码,程序并不能直接展现变化,必须再次经过一次 maven 编译和拷贝更新。
而挂载则是将源码路径src/main/resources追加到 classpath 上,使得源码修改可以立刻生效,而无需编译,便于开发。
part2: 使用外部配置控制 Spring Application
使用外部配置控制指的是 application.properties / yml
Spring Application 中修改配置使用 Java API。
这里教程说到:application.properties 中可以使用 spring.main.* 来改变 spring Application 的一些配置,被称为外部化配置(实质是配置的映射),而与此相对的,写在 Application 中的则是硬编码。
例如,以下的代码在properties中关闭了打印 spring banner 的配置
1 | spring.main.banner-mode = off |
既然这里说到application.properties / yml可以通过 Spring Application 映射的 spring.main.* 修改属性,则我们可以发现两种设置存在优先级:外部配置 > Java API。
普通配置项(如 Banner、Web类型、port 等)遵循这个优先级,是 Java API < 外部配置。
但存在例外:主配置源(primary sources)。
TIP:何为主配置源
根据官方定义,primary sources 是指传给SpringApplication构造函数(或SpringApplicationBuilder.sources()方法)的那些 class 类或 package,它们是用于引导和创建 spring 应用上下文的顶级配置起点(ApplicationContext)。 主配置源可以有多个,但一般只传一个主类(即有 main() 并有@SpringBootApplication的那个类)。 主配置源通常贴着@SpringBootApplication` 注解,是整个 Spring 容器的艮起点。
一般来说长这样:
1 | // MyApplication.class 是主配置源 |
part3:修改应用外部属性的位置
这个标题在第一次看到时会觉得一头雾水,实际上,这一部分讲的是如何让 Spring Boot 正确读取自定义配置文件,以及给出了配置不生效时(也就是读取失败时)如何通过日志排查。
我们都用过 spring initializr 拉过 spring 框架,也都知道外部配置 application.properties / yml 中读取配置的(Spring 默认从…)。但在实际生产中,我们可能会修改 .yml 文件名称或位置。
举一个大家都遇到过的问题——模版接入的 api key 注入,这些配置出于安全考虑,都会直接写在项目的外部配置中。因此,如何让 Spring 读到这些应用外部属性呢?
一般是通过命令行 / 系统属性 / 环境变量在程序启动时修改两个参数:spring.config.name 和 spring.config.location
前者适用于仅修改名称而文件读取路径不变的情况,后者直接修改查找路径。
1 | java -jar app.jar --spring.config.name=myapp |
为什么通过外部环境传入?
因为读取配置文件之前就需要知悉文件读取路径,只有命令行 / 系统属性 / 环境变量可以做到。
排查配置不生效的方法:trace 日志
官方提供的排查方法如下:
1 | java -jar app.jar --logging.level.org.springframework.boot.context.config=true |
part4:使用“简短”的 cmd 参数
这里介绍的是 port 的简短配置方式,操作方式是:
在 application.properties / yml 中:
1 | server.port = ${port:8080} |
TIP:这里的${变量名 :默认值}
这样 port 在命令行中就可代替 server.port,并且有了默认值 8080。
这样做也使得在 Docker、Heroku 等平台部署更方便,因为在 PaaS 环境中分配端口注入方式为 PORT,也就可以被正确识别为 server.port 并注入。
part5:使用 YAML 作为外部属性配置
yaml 是 json 的超集,不难看出两者格式与语法区别很相似。
1 | # yaml |
1 | # json |
.yaml 解析所需依赖包含在 spring-boot-starter 中。解析后由树状变为如 properties 一样的单层,生成以 . 分隔的键。
由于 yaml 树状结构清晰,一般复杂项目都会采用 yaml,而不是 properties。
part6:设置激活的 Spring Profile
什么是 profile,我们为什么要激活它?
profile 是 spring 框架提供的一种环境隔离机制,它允许开发者把针对不同运行环境的配置和组件分隔开,当某一 profile 被激活,对应的配置和组件才会生效。
在开发过程中,我们需要在不同环境中运行一套代码,通常会有:dev 开发环境 prod 生产环境 。这些环境的数据库连接、日志级别、API 注入方式等都会存在很大差异,而每次手动修改配置则很容易出错也很吃力。于是我们引入了profile,便于快速切换环境。
那profile具体要怎么写,写在哪里呢?
profile 是由 Java 代码与配置文件共同完成的
在 Java 代码中,一般用于加载组件
1 |
|
在配置文件中一般控制配置参数具体数值:
1 | # application-dev.yml |
当激活某一 profile 时,相关的 Java 代码和配置文件(包括通用的 application.yml 与对应的 application-profile.yml )会被激活。
这里配置文件划分 profile有两种方式:
- 第一种是分为多个 yml 文件:
application.yml— 通用application-dev.yml— 不同 profileapplication-prod.yml
- 第二种是
application.yml中用#---分区。例如:
1 | # properties |
其中激活的 profile 设置可覆盖默认。
那如何激活 profile 呢?
在启动程序时指定激活命令,如:
1 | --spring.profiles.active=prod |
default profile 如何设置呢?
在 application.properties 中可设置 default profile:
1 | spring.profiles.default=dev |
学到这里,我们已经读完了官方教程的大部分内容,对于Configuration和Properties也有了大致的认识和掌握!关于具体如何写,在下一次笔记中会写到。