說一個(gè)大家都知道的 Spring Boot 小細(xì)節(jié)!
小伙伴們知道,我們在創(chuàng)建 Spring Boot 項(xiàng)目的時(shí)候,默認(rèn)都會(huì)有一個(gè) parent,這個(gè) parent 中幫我們定了項(xiàng)目的 JDK 版本、編碼格式、依賴版本、插件版本等各種常見內(nèi)容,有的小伙伴可能看過 parent 的源碼,這個(gè)源碼里邊有這么一個(gè)配置:
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
</resource>
<resource>
<directory>${basedir}/src/main/resources</directory>
<excludes>
<exclude>**/application*.yml</exclude>
<exclude>**/application*.yaml</exclude>
<exclude>**/application*.properties</exclude>
</excludes>
</resource>
</resources>
首先小伙伴們知道,這個(gè)配置文件的目的主要是為了描述在 maven 打包的時(shí)候要不要帶上這幾個(gè)配置文件,但是咋一看,又感覺上面這段配置似乎有點(diǎn)矛盾,松哥來和大家捋一捋就不覺得矛盾了:
- 先來看第一個(gè) resource,directory 就是項(xiàng)目的 resources 目錄,includes 中就是我們?nèi)N格式的配置文件,另外還有一個(gè) filtering 屬性為 true,這是啥意思呢?這其實(shí)是說我們在 maven 的 pom.xml 文件中定義的一些變量,可以在 includes 所列出的配置文件中進(jìn)行引用,也就是說 includes 中列出來的文件,可以參與到項(xiàng)目的編譯中。
- 第二個(gè) resource,沒有 filter,并且將這三個(gè)文件排除了,意思是項(xiàng)目在打包的過程中,除了這三類文件之外,其余文件直接拷貝到項(xiàng)目中,不會(huì)參與項(xiàng)目編譯。
總結(jié)一下就是 resources 下的所有文件都會(huì)被打包到項(xiàng)目中,但是列出來的那三類,不僅會(huì)被打包進(jìn)來,還會(huì)參與編譯。
這下就清晰了,上面這段配置實(shí)際上并不矛盾。
那么在 properties 或者 yaml 中,該如何引用 maven 中的變量呢?
這塊原本的寫法是使用$ 符號來引用,但是,我們在配置文件中,往往用 $符號來引用當(dāng)前配置文件的另外一個(gè) key,所以,我們在 Spring Boot 的 parent 中,還會(huì)看到下面這行配置:
<properties>
<java.version>17</java.version>
<resource.delimiter>@</resource.delimiter>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
這里的 <resource.delimiter>@</resource.delimiter> 就表示將資源引用的符號改為 @ 符號。也就是在 yaml 或者 properties 文件中,如果我們想引用 pom.xml 中定義的變量,就可以通過 @ 符號來引用。
松哥舉一個(gè)簡單的例子,假設(shè)我想在項(xiàng)目的 yaml 文件中配置當(dāng)前項(xiàng)目的 Java 版本,那么我就可以像下面這樣寫:
app:
java:
version: @java.version@
這里的 @java.version@ 就表示引用了 pom.xml 中定義的 java.version 變量。
現(xiàn)在我們對項(xiàng)目進(jìn)行編譯,編譯之后再打開 application.yaml,內(nèi)容如下:
可以看到,引用的變量已經(jīng)被替換了。
按照 Spring Boot parent 中默認(rèn)的配置,application*.yaml、application*.yml 以及 application*.properties 文件中可以引用 pom.xml 中定義的變量,其他文件則不可以。如果其他文件也想引用,就要額外配置一下。
例如,想讓 txt 文件引用 pom.xml 中的變量,我們可以在 pom.xml 中做如下配置:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.txt</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
include 所有的 txt 文件,并且設(shè)置 filtering 為 true(不設(shè)置默認(rèn)為 false),然后我們就可以在 resources 目錄下的 txt 文件中引用 pom.xml 中的變量了,像下面這樣:
編譯之后,這本變量引用就會(huì)被替換成真正的值:
在 yaml 中引用 pom.xml 的配置,有一個(gè)非常經(jīng)典的用法,就是多環(huán)境切換。
假設(shè)我們現(xiàn)在項(xiàng)目中有開發(fā)環(huán)境、測試環(huán)境以及生產(chǎn)環(huán)境,對應(yīng)的配置文件分別是:
- application-dev.yaml
- application-test.yaml
- application-prod.yaml
我們可以在 application.yaml 中指定具體使用哪個(gè)配置文件,像下面這樣:
spring:
profiles:
active: dev
這個(gè)表示使用開發(fā)環(huán)境的配置文件。
但是有時(shí)候我們的環(huán)境信息是配置在 pom.xml 中的,例如 pom.xml 中包含如下內(nèi)容:
<profiles>
<profile>
<id>dev</id>
<properties>
<package.environment>dev</package.environment>
</properties>
<!-- 是否默認(rèn) true表示默認(rèn)-->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<package.environment>prod</package.environment>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<package.environment>test</package.environment>
</properties>
</profile>
</profiles>
這里配置了三個(gè)環(huán)境,其中默認(rèn)是 dev(activeByDefault)。那么我們在 application.yaml 中就可以使用 package.environment 來引用當(dāng)前環(huán)境的名稱,而不用硬編碼。如下:
spring:
profiles:
active: @package.environment@
此時(shí),我們通過 maven 命令對項(xiàng)目打包時(shí),就可以指定當(dāng)前環(huán)境的版本了,例如使用 test 環(huán)境,打包命令如下:
mvn package -Ptest
打包之后我們?nèi)タ?application.yaml,就會(huì)發(fā)現(xiàn)里邊的環(huán)境已經(jīng)是 test 了。
如果你使用的是 IDEA,則也可以手動(dòng)勾選環(huán)境之后點(diǎn)擊打包按鈕,如下:
可以先勾選上面的環(huán)境信息,再點(diǎn)擊下面的打包。
好啦,一個(gè)小小知識(shí)點(diǎn),因?yàn)橛行』锇樵谖⑿派蠁栠@個(gè)問題,就拿出來和大家分享下。