When you create a Spring Boot project, there is a parent by default, which helps us determine the project’s JDK version, coding format, dependency version, plugin version, and various other common things. Some of you may have seen the source code of the parent, which has a configuration like this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<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>

First of all, the purpose of this configuration file is mainly to describe whether to package the configuration files in the maven build, but at first glance, the above configuration seems to be a bit contradictory.

  1. First look at the first resource, directory is the project’s resources directory, includes in the three formats of the configuration file, in addition there is a filtering attribute for true, what does this mean? This actually means that some variables defined in maven’s pom.xml file can be referenced in the configuration files listed in includes, which means that the files listed in includes can be involved in the compilation of the project.
  2. The second resource, without filter, and with these three files excluded, means that the project is built with all but these three types of files copied directly into the project and will not participate in the project compilation.

To summarize, all files under resources will be packaged into the project, but the three categories listed will not only be packaged in, but will also be involved in the compilation.

This makes it clear that the above configuration is not actually contradictory.

So how do you reference the variables in maven in properties or yaml?

The original way to write this is to use the $ symbol to reference it, but we often use the $ symbol in the properties configuration file to reference another key in the current configuration file, so we will see the following line in the Spring Boot parent.

1
2
3
4
5
6
7
8
<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>

The <resource.delimiter>@</resource.delimiter> means that the resource reference symbol is changed to the @ symbol. That is, in yaml or properties files, if we want to refer to variables defined in pom.xml, we can do so with the @ symbol.

For a simple example, let’s say I want to configure the current project’s Java version in the project’s yaml file, then I can write it like this.

1
2
3
app:
  java:
    version: @java.version@

The @java.version@ here is a reference to the java.version variable defined in pom.xml.

Now we compile the project, and after compiling it, we open application.yaml, which reads as follows:

application.yaml

As you can see, the referenced variables have been replaced.

According to the default configuration in Spring Boot parent, the variables defined in pom.xml can be referenced in application*.yaml, application*.yml, and application*.properties files, but not in other files. If you want to refer to other files as well, you need to configure them additionally.

For example, if we want the txt file to refer to variables in pom.xml, we can do the following configuration in pom.xml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<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>

After including all txt files and setting filtering to true (the default is false if not set), we can then reference the variables in pom.xml in the txt file in the resources directory, like this:

the txt file

After compilation, this variable reference will be replaced with the real value.

the txt file

A very classic use of pom.xml configuration in yaml is to switch between multiple environments.

Assuming we have a development environment, a test environment, and a production environment in our project, the corresponding configuration files are

  • application-dev.yaml
  • application-test.yaml
  • application-prod.yaml

We can specify which configuration file to use in application.yaml, like the following:

1
2
3
spring:
  profiles:
    active: dev

This indicates the configuration file that uses the development environment.

But sometimes our environment information is configured in pom.xml, for example, pom.xml contains the following.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <package.environment>dev</package.environment>
        </properties>
        <!-- Default or not, true means default-->
        <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>

Three environments are configured here, where the default is dev (activeByDefault). Then we can use package.environment in application.yaml to refer to the current environment name without hard coding. As follows:

1
2
3
spring:
  profiles:
    active: @package.environment@

At this point, we can specify the version of the current environment when packaging the project through the maven command, for example, using the test environment, the packaging command is as follows.

1
mvn package -Ptest

After packaging, we will look at application.yaml and see that the environment in it is already test.

If you are using IDEA, you can also manually check the environment and click the package button, as follows:

IDEA

You can check the environment information above first, then click Compile below.

Reference: https://segmentfault.com/a/1190000043737583