In the Quick Start section, we have easily implemented a simple RESTful API application and experienced many advantages of Spring Boot. We have successfully implemented a Web application with very little code, which is not possible with traditional Spring applications. Although the code we used to implement Controller is the same, in terms of configuration, you may have noticed that in the example above, no configuration is introduced beyond the Maven configuration.

As mentioned earlier, Spring Boot provides a series of automated configurations for our common development scenarios to reduce the complexity of templating configurations that rarely change. However, we still need to understand how to modify these automated configurations in Spring Boot for specific scenarios, such as: We need to launch multiple Spring Boot based Web applications on the same host, and if we do not specify a special port number for each application, the default port 8080 will inevitably cause a conflict.

If you’re still reading my Spring Cloud tutorial series, a lot of the work is going to be on configuration files. Therefore, it is necessary to learn more about the configuration file in Spring Boot, such as how it is configured, how to implement multi-environment configuration, and the loading sequence of configuration information.

Configure the base

In the quick start example, when we introduced the Spring Boot engineering structure, we mentioned that the SRC /main/resources directory is the Spring Boot configuration directory, so it is under this directory that we will create the configuration personalizations for our application.

Spring Boot a default configuration file location is: the SRC/main/resources/application. The properties. The configuration of the Spring Boot application is in this file. Depending on the Starter module we introduce, you can define various configuration information such as container port name, database link information, log level, and so on. For example, if we need to customize the service port number for our Web module, we can specify the service port 8888 by adding server.port=8888 in application.properties. You can also specify the application name (which is registered as the service name in the Spring Cloud application) by spring.application.name=hello.

In addition to the traditional Properties files, Spring Boot’s configuration files also support the now widely recommended YAML files.

YAML (/ˈ k æməl/) is a readable format used to express sequences of data. YAML references a number of other languages, including C, Python, Perl, and takes inspiration from XML, the data format for E-mail (RFC 2822). Clark Evans first published the language in 2001, and Ingy Dot Net and Oren Ben-Kiki are co-designers of the language. Several programming or scripting languages already support (or parse) this language. YAML is a recursive abbreviation of “YAML Ain’t a Markup Language”. At the time of development, YAML actually meant “Yet Another Markup Language” (still a Markup Language), but was renamed in reverse abbreviations to emphasize its data-centric, rather than mark-up, focus. The syntax of AML is similar to that of other high-level languages, and it is easy to express data forms such as lists, hash tables, scalars, and so on. It uses white space indentation and a heavy dependency on appearance, making it particularly suitable for expressing or editing data structures, various configuration files, slanting debugging content, and document Outlines (for example, many E-mail header formats are very similar to YAML). Although it is more suitable for expressing hierarchical model data structures, there is also a sophisticated syntax for expressing relational Model data. YAML is especially good for grep/Python/Perl/Ruby operations because it uses blank characters and lines to separate data. One of its most accessible features is the clever avoidance of closing symbols, such as quotation marks and parentheses, which can become complicated and difficult to read in nested structures. “– Wikipedia

The configuration format adopted by YAML is not represented as a simple key-value pair like that of Properties, but as an indentation like an outline. For example: the following YAML configuration information

environments:
    dev:
        url: http://dev.bar.com
        name: Developer Setup
    prod:
        url: http://foo.bar.com
        name: My Cool App
Copy the code

The equivalent properties configuration is as follows.

environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App
Copy the code

With the YAML configuration, we can see that the configuration information is more legible by using the stepwise indentation, and the configuration content is significantly reduced in character size. In addition, YAML can define multiple different environment configurations in a single file by using the Spring.profiles property. For example, if the test environment is specified, server.port will use port 8882. In the Prod environment, server.port will use port 8883; If no environment is specified, server.port will use port 8881.

server:
    port: 8881
---
spring:
    profiles: test
server:
    port: 8882
---
spring:
    profiles: prod
server:
    port: 8883
Copy the code

Note: YAML currently has some drawbacks, it will not pass@PropertySourceAnnotations to load the configuration. However, YAML loads properties into memory in order, so when the information in a configuration file needs to have a sequential meaning, the YAML configuration approach has advantages over the Properties configuration file.

Custom parameter

In addition to setting the predefined properties of each Starter module in the Spring Boot configuration file, we can also define some custom properties in the configuration file that we need. For example, in application.properties add:

book.name=SpringCloudInAction
book.author=ZhaiYongchao
Copy the code

We can then load these custom parameters in the application via the @value annotation, such as:

@Component
public class Book {

    @Value("${book.name}")
    private String name;
    @Value("${book.author}")
    private String author;

    // Omit the getter and setter
}
Copy the code

The @value annotation supports two types of configuration when loading property values:

  • One is the PlaceHolder method that we introduced above, which has the formatThe ${... }PlaceHolder in curly
  • You can also use SpEL expressions (Spring Expression Language) in the format of# {... }, the SpEL expression is enclosed in braces

Parameters of the reference

We can also use PlaceHolder references directly between the parameters in application.properties, as shown in the following:

book.name=SpringCloud
book.author=ZhaiYongchao
book.desc=${book.author}Is writing"${book.name}"Copy the code

The book.desc parameter refers to the book.name and book.author properties defined above, and the final value of this property is that ZhaiYongchao is writing SpringCloud.

Use random numbers

In some special cases, we want parameters that are not fixed each time they are loaded, such as key, service port, etc. In the Spring Boot property profile, we can use the ${random} configuration to generate random int, long, or string values. This makes it easy to generate random properties by configuring them, rather than coding them in the program.

${random} can be used as a reference.

# Random string
com.didispace.blog.value=${random.value}
# random int
com.didispace.blog.number=${random.int}
# random long
com.didispace.blog.bignumber=${random.long}
Random number up to # 10
com.didispace.blog.test1=${random.int(10)}
Random number # 10-20
com.didispace.blog.test2=The ${random. Int [10, 20]}
Copy the code

This configuration method can be used to set application ports to avoid port conflicts during local debugging

Command line arguments

Recall that in the Quick Start section of this chapter, we also covered how to launch the Spring Boot application, including the java-jar command. In addition to starting the application, you can also specify the application parameters in the command line, for example, Java -jar xxx.jar –server.port=8888. You can directly set the server.port property in the command line, and set the port for starting the application to 8888.

When the Spring Boot application is started from the command line, two consecutive minus signs — the identification of the value assigned to the property in application.properties. So, the Java -jar xxx.jar –server.port=8888 command is equivalent to adding the property server.port=8888 to application.properties.

Using the command line to modify property values is an important feature of Spring Boot. By using this feature, we theoretically make the properties of our application variable before startup, so the port number and database connection can be changed during startup. Unlike previous Spring applications, Maven profiles are used to build different environments in the compiler. The biggest difference is that Spring Boot’s approach allows applications to be packaged throughout development, testing, and online deployment, whereas Maven’s different Profile solutions build packages that are essentially different for each environment. However, if every argument needs to be specified on the command line, this is obviously not a good option either, so let’s look at how to configure multiple environments in Spring Boot.

Multi-environment configuration

When we develop any application, it is common for the same program to be applied and installed in several different environments, such as development, test, production, etc. Each environment has different configurations for database addresses, server ports, and so on, and it can be tedious and error-prone to change configuration files frequently when packaging for different environments.

For multi-environment configuration, the basic idea of various project build tools or frameworks is the same. By configuring multiple configuration files for different environments, and then using the packaging command to specify the contents to be packaged, and then differentiate packaging, Spring Boot is no exception, or even simpler.

{profile} corresponds to your environment id, such as:

  • application-dev.properties: Development environment
  • application-test.properties: Test environment
  • application-prod.properties: Production environment

Which specific profile will be loaded needs to be set in the application.properties file via the spring.profiles. Active property, which corresponds to the {profile} value in the profile. For example, spring.profiles. Active =test loads the content of the application-test.properties configuration file.

The following uses different service ports configured in different environments as an example.

  • Create configuration files application-dev.properties, application-test.properties, and application-prod.properties for each environment

  • Set server.port properties for each of the three files, such as 1111 for dev, 2222 for test, and 3333 for Prod

  • Spring.profiles. Active =dev in application.properties, which means that the default setting is the dev environment

  • Test the loading of different configurations

  • Execute Java -jar xxx.jar and observe that the service port is set to 1111, the default development environment (dev).

  • Java -jar xxx.jar –spring.profiles. Active =test and you can see that the service port is set to 2222, which is the configuration of the test environment (test).

  • Execute Java -jar xxx.jar –spring.profiles.active=prod and you can observe that the service port is set to 3333, which is the production environment configuration (PROD).

According to the above experiment, the configuration idea of multiple environments can be summarized as follows:

  • application.propertiesTo configure common content and setspring.profiles.active=devWith the development environment as the default configuration
  • application-{profile}.propertiesTo configure different content for each environment
  • This section describes how to deactivate the configuration of different environments on the CLI

Load order

In the example above, we put all the configuration required for the Spring Boot application in the project, although we can already implement multi-environment support either through Spring.profiles. Active or through Maven. However, as our teams grew and the division of labor became more detailed, we often didn’t need to let the developers know the details of the test or build environment, and wanted the information to be centrally maintained by the individual responsible for each environment (QA or operations). If you still store the configuration content in this way, you have to get the project content to modify the configuration content for different environment configurations, which becomes very inconvenient when the application is very large. At the same time, the configuration content is visible to developers, which is itself a security hazard. For this reason, there are many frameworks and tools that externalize the configuration content. Spring Cloud Config is one of them. In order to better understand the loading mechanism of Spring Cloud Config, Some understanding of Spring Boot’s mechanism for loading data files is needed.

Spring Boot uses the following special property loading order in order to properly override the values of each property:

  1. Arguments passed in from the command line.
  2. SPRING_APPLICATION_JSONProperty in.SPRING_APPLICATION_JSONIs the content configured in the system environment variable in JSON format.
  3. java:comp/envIn theJNDIProperties.
  4. Java system properties can be passedSystem.getProperties()Obtained content.
  5. Environment variables of the operating system
  6. throughrandom.*Random properties to be configured
  7. Located outside the current application JAR package, for different{profile}The configuration file content of the environment, for example:application-{profile}.propertiesorYAMLThe configuration file defined
  8. In the current application JAR package, for different{profile}The configuration file content of the environment, for example:application-{profile}.propertiesorYAMLThe configuration file defined
  9. Outside of the current application JAR packageapplication.propertiesandYAMLConfigure the content
  10. Within the current application JAR packageapplication.propertiesandYAMLConfigure the content
  11. in@ConfigurationAnnotations modify the class through@PropertySourceAttributes defined by annotations
  12. To apply the default properties, useSpringApplication.setDefaultPropertiesDefined content

The priority is in descending order. The smaller the number, the higher the priority.

As you can see, item 7 and item 9 read the configuration file from outside the application JAR package, so the principle of externalizing the configuration is to start here and specify the location where the external configuration file is loaded instead of the configuration content inside the JAR package. Through this implementation, our project will be very clean in configuration, we only need to place the configuration needed for development locally, and the configuration of other environments can be maintained by the person in charge of the corresponding environment.

2. The new feature x

Spring Boot 2.0 released Relaxed Binding 2.0, which makes a lot of improvements to the old property Binding feature to make it easier to load and read configuration information in Spring applications. The following article takes a look at the configuration improvements in Spring Boot 2.0.

Configuring File Binding

A simple type

In addition to removing special characters as in 1.x, Spring Boot 2.0 also matches and loads configuration properties in all lower case. Therefore, the following four configurations are equivalent:

  • The properties formats:
spring.jpa.databaseplatform=mysql
spring.jpa.database-platform=mysql
spring.jpa.databasePlatform=mysql
spring.JPA.database_platform=mysql
Copy the code
  • Yaml formats:
spring:
  jpa:
    databaseplatform: mysql
    database-platform: mysql
    databasePlatform: mysql
    database_platform: mysql
Copy the code

Tips: It is recommended to use all lower case-Delimiters, such as:spring.jpa.database-platform=mysql

List the type

Use [] in the properties file to locate the list type, for example:

spring.my-example.url[0]=http://example.com
spring.my-example.url[1]=http://spring.io
Copy the code

The comma-separated configuration is also supported. The above configuration is equivalent to the following:

spring.my-example.url=http://example.com,http://spring.io
Copy the code

In the YAML file, you can use the following configuration:

spring:
  my-example:
    url:
      - http://example.com
      - http://spring.io
Copy the code

Commas are also supported:

spring:
  my-example:
    url: http://example.com, http://spring.io
Copy the code

Note: In Spring Boot 2.0, the configuration of the List type must be sequential, otherwise it will be thrownUnboundConfigurationPropertiesExceptionException. Therefore, the following configurations are not allowed:

foo[0]=a
foo[2]=b
Copy the code

This is possible in Spring Boot 1.x,foo[1]Since it is not configured, its value will benull

The Map type

The Map type is configured as follows in properties and YAML:

  • The properties formats:
spring.my-example.foo=bar
spring.my-example.hello=world
Copy the code
  • Yaml formats:
spring:
  my-example:
    foo: bar
    hello: world
Copy the code

Note: If Map type key contains non-alphanumeric and-Is required to use[]In brackets, as:

spring:
  my-example:
    '[foo.baz]': bar
Copy the code

Environment property binding

A simple type

Convert to and by lowercase in the environment variable. Replace _ to map the contents of the configuration file, such as: environment variables SPRING_JPA_DATABASEPLATFORM = mysql configuration will generate and set in the configuration file spring. Jpa. Databaseplatform = the same effect as mysql.

List the type

Since the [and] symbols cannot be used in environment variables, _ is used instead. Any number surrounded by underscores is considered an array of []. Such as:

MY_FOO_1_ = my.foo[1]
MY_FOO_1_BAR = my.foo[1].bar
MY_FOO_1_2_ = my.foo[1][2]
Copy the code

In addition, if the last environment variable ends with a number or an underscore, the last underscore can be omitted. For example, the first and third items in the above example are equivalent to the following configuration:

MY_FOO_1 = my.foo[1]
MY_FOO_1_2 = my.foo[1][2]
Copy the code

System property binding

A simple type

System properties as similar to that in the configuration file to remove all special characters and binding after transformation lowercase, such as the spring will implement the following command line parameters configuration. Jpa. Databaseplatform = mysql effect:

-Dspring.jpa.database-platform=mysql
-Dspring.jpa.databasePlatform=mysql
-Dspring.JPA.database_platform=mysql
Copy the code

List the type

System property bindings are similar to file property bindings and are identified by [], for example:

-D"spring.my-example.url[0]=http://example.com"
-D"spring.my-example.url[1]=http://spring.io"
Copy the code

Similarly, he supports comma separation, such as:

-Dspring.my-example.url=http://example.com,http://spring.io
Copy the code

Reading properties

You can see that there are many different ways to express a property, but if we want to read the property in the Spring application’s environment, the unique name of each property conforms to the following rules:

  • through.Separate the elements
  • The last one.Separate the prefix from the attribute name
  • Must be letters (A-Z) and numbers (0-9)
  • It must be lowercase letters
  • Use a hyphen-To separate words
  • The only other characters allowed are[and], for the index of the List
  • It must not start with a number

So, if we wanted to read the spring.jpa.database-platform configuration from the configuration file, we could write:

this.environment.containsProperty("spring.jpa.database-platform")
Copy the code

The spring.jpa.database-platform configuration cannot be obtained using the following method:

this.environment.containsProperty("spring.jpa.databasePlatform")
Copy the code

Note: Use@ValueThis feature is also required when obtaining the configuration content

New binding API

New binding apis have been added to Spring Boot 2.0 to make it easier to get configuration information. Here’s an example to make it easier:

Example 1: Simple types

Suppose there is a configuration in the propertes configuration: com.didispace. Foo =bar

We create the corresponding configuration class for it:

@Data
@ConfigurationProperties(prefix = "com.didispace")
public class FooProperties {

    private String foo;

}
Copy the code

Next, configuration information can be obtained with the latest Binder:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(Application.class, args);

        Binder binder = Binder.get(context.getEnvironment());

        // Bind simple configuration
        FooProperties foo = binder.bind("com.didispace", Bindable.of(FooProperties.class)).get(); System.out.println(foo.getFoo()); }}Copy the code

Example 2: The List type

What if the configuration content is of type List? Such as:

com.didispace.post[0]=Why Spring Boot
com.didispace.post[1]=Why Spring Cloud

com.didispace.posts[0].title=Why Spring Boot
com.didispace.posts[0].content=It is perfect!
com.didispace.posts[1].title=Why Spring Cloud
com.didispace.posts[1].content=It is perfect too!
Copy the code

Getting these configurations is still simple, and can be done as follows:

ApplicationContext context = SpringApplication.run(Application.class, args);

Binder binder = Binder.get(context.getEnvironment());

// Bind the List configuration
List<String> post = binder.bind("com.didispace.post", Bindable.listOf(String.class)).get();
System.out.println(post);

List<PostInfo> posts = binder.bind("com.didispace.posts", Bindable.listOf(PostInfo.class)).get();
System.out.println(posts);
Copy the code

Code sample

This tutorial supports the warehouse:

  • Github:github.com/dyc87112/Sp…
  • Gitee:gitee.com/didispace/S…

If you think this article is good, welcome to Star, Follow support! Your attention is the power of my persistence!

reading

  • Spring Boot 1.x: details of the property configuration file
  • Spring Boot 2.0: Configures binding 2.0 full resolution