Let’s talk about a small detail of Spring Boot that everyone knows!

Friends know that when we create a Spring Boot project, there will be a parent by default. This parent helps us determine various common contents such as the JDK version, encoding format, dependency version, plug-in version, etc. of the project. Some friends You may have seen the source code of parent. There is such a configuration in the source code:

< 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, friends know that the purpose of this configuration file is mainly to describe whether to bring these configuration files when maven is packaged. However, at first glance, I feel that the above configuration seems a bit contradictory. Brother Song is here to tell you. After a quick glance, you no longer feel the contradiction:

  1. Let’s look at the first resource first. Directory is the resources directory of the project. Includes are our configuration files in three formats. There is also a filtering attribute of true. What does this mean? This actually means that some variables we 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 participate in the compilation of the project.
  2. The second resource has no filter and excludes these three files, which means that during the project packaging process, except for these three types of files, the remaining files are copied directly to the project and will not participate in project compilation.

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

It is now clear that the above configuration is not actually contradictory.

So how to reference variables in maven in properties or yaml?

The original way of writing this block is to use $the symbol to refer to it. However, in the properties configuration file, we often use $the symbol to refer to another key of the current configuration file. Therefore, we will also see the following line in the parent of Spring Boot. Configuration:

< 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 >

Here <resource.delimiter>@</resource.delimiter>means changing the symbol of the resource reference to @the symbol. That is, in the yaml or properties file, if we want to reference the variables defined in pom.xml, we can @reference them through the symbol.

Brother Song gives a simple example. Suppose I want to configure the Java version of the current project in the project’s yaml file. Then I can write as follows:

    version:  @java.version@

Here @java.version@it means referencing java.versionthe variables defined in pom.xml.

Now we compile the project and open application.yaml after compilation. The content is as follows:

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

According to the default configuration in Spring Boot parent, variables defined in pom.xml can be referenced in application .yaml, application .yml and application*.properties files, but other files cannot. If other files also want to be referenced, additional configuration is required.

For example, if we want the txt file to reference variables in pom.xml, we can make the following configuration in 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 
    <artifactId> spring - boot - maven - plugin </artifactId> 
        </plugin> </plugins> < / build​​​​​​​​​​​​​​​​​​ >

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

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

There is a very classic usage of quoting the configuration of pom.xml in yaml, which is to switch between multiple environments.

Assume that our current project has a development environment, a test environment and a production environment. 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 this:

    active:  dev

This indicates using the configuration file of the development environment.

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

< profiles > 
    < profile > 
        < id > dev </ id > 
        < properties > 
            < package.environment > dev </ package.environment > 
        </ properties > 
        <!-- Whether the default 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, the default is dev (activeByDefault). Then we can use package.environment in application.yaml to refer to the name of the current environment without hard coding. as follows:

    active:  @package.environment@

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

mvn package  -Ptest

After packaging, if we look at application.yaml, we will find that the environment inside is already test.

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

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

Okay, a little knowledge point. Because some friends asked this question on WeChat, I will share it with everyone.