Spring Boot configuration file pattern, see this one enough!

In the Quick Start section, we easily achieve a simple RESTful API application, experience a bit Spring Boot brought us many advantages, we use a very small amount of code on the successful implementation of a Web application, which is the traditional Spring application can not be done, though the code we use when implementing Controller is the same, but in the configuration, I believe we have noticed, in the example above, except after Maven configuration, it does not introduce any Configuration.

This is before we mentioned, Spring Boot offers a range of automated configuration for our common development scenarios to reduce the original complex and rarely change the configuration of templated content. However, we still need to understand how to modify these automated configuration content in Spring Boot in order to respond to the needs of some special scenarios, such as: we need to launch multiple web application based on Spring Boot on the same host, as if we do not each application specifies the particular port number, the default port 8080 is bound to lead to conflict.

If you have read my Spring Cloud tutorial series , in fact, there will be a lot of work for the configuration file. Therefore, we need in-depth knowledge of some configuration files on Spring Boot in, for example: it is configured, how to achieve multi-environment configuration, the configuration information such as load order.

Configuration Basics

In the quick start when the example, we introduced Spring Boot engineering structures, there are mentioned src/main/resourceswhen the directory is a Spring Boot configuration directory, so we have to create a configuration customized configuration for the application is under the directory.

The default configuration file location Spring Boot as follows: src/main/resources/application.properties. About Spring Boot configuration content can be focused on the application of this document, and depending on the Starter module we introduced here can be defined as: a container port name, database links information, log levels and other configuration information. For example, we need to customize the service port number of the web module, you can application.propertiesadd in server.port=8888to specify the service port is 8888, you can also spring.application.name=hellospecify the application name (the name Spring Cloud applications will be registered as a service name) to.

Spring Boot configuration files in addition to using the traditional file properties, but also support the now widely recommended YAML file.

YAML (English pronunciation: / jæməl /, tail similar to camel camel) is a highly readable, format for expressing data series. YAML reference to other languages, including: C, Python, Perl, and get inspiration from XML, e-mail data format (RFC 2822) in. Clark Evans in 2001 for the first time published the language, in addition Ingy döt Net and Oren Ben-Kiki is also the designer of this common language. Now there are several programming or scripting language support (or resolve) this language. YAML is "YAML Is not a Markup Language" (YAML is not a markup language) is recursive acronym. In the development of the language, YAML meant in fact: "Yet Another Markup Language" (still a markup language), but in order to emphasize the language as a data center, rather than focusing on the markup language, and rename it with the reverse abbreviations. AML and other high-level language syntax is similar to, and may simply express the list, hash, scalar and other information form. It uses blank sign indentation and rely heavily on the characteristics of appearance, particularly suitable for expressing or edit data structure, various profiles, debug dump the contents of the file outline (e.g.: mail header formats and many YAML very close) . Although it is more suitable for expressing a hierarchical data structure (hierarchical model), but also with fine syntax can represent data association (relational model) of. Since the character and a blank YAML branches to separate the data, making it particularly suitable for use grep / Python / Perl / Ruby operation. It makes the most ingenious feature is easy to use to avoid the closure of various symbols, such as: quotes, various brackets, etc., these symbols in the nested structure can become complex and difficult to identify. -- Wikipedia

YAML configuration format used properties like configuration as simple key-value pairs to be represented in the form, but the form is similar to the outline of indentation to represent. For example: The following paragraph YAML configuration information

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

Properties equivalent thereto is configured 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

By YAML configuration, we can see the configuration information using ladder-indented way, its structure is more legible, while the amount of character configuration content has also been significantly reduced. In addition, YAML can also be used in a single file spring.profilesto define a plurality of different environment configuration attributes. For example, the following content, as specified in test environment, server.portthe use of port 8882; in prod environment, server.portuses port 8883; if not specified environment, server.portwill use the 8881 port.

server:
    port: 8881
---
spring:
    profiles: test
server:
    port: 8882
---
spring:
    profiles: prod
server:
    port: 8883

Note: YAML there are still some shortcomings, it can not pass @PropertySourceto load the configuration annotations. However, YAML attributes when loading into memory preservation is ordered, so when the information in the configuration file need to have the order of meaning, YAML configuration compared to the properties of the configuration files advantage.

Custom parameters

We can set apart from each module Starter predefined configuration properties in Spring Boot configuration file, you can also define custom attributes we need in the configuration file. For example, in application.propertiesadding:

book.name=SpringCloudInAction
book.author=ZhaiYongchao

Then, in the application we can @Valueto load these parameters to customize the annotation, such as:

@Component
public class Book {

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

    // 省略getter和setter
}

@ValueWhen loaded annotation attribute values ​​can be configured to support two expressions:

  • One is PlaceHolder way we described above, the format  ${...} , braces for the PlaceHolder
  • Also available is SpEL expression (Spring Expression Language), the format  #{...} , braces for the expression SpEL

Parameter references

In application.propertiesbetween the various parameters, we can also be referenced directly by using PlaceHolder way, as the following settings:

book.name=SpringCloud
book.author=ZhaiYongchao
book.desc=${book.author}  is writing《${book.name}》

book.descParameters defined above references book.nameand book.authorattributes, the last value of the property is ZhaiYongchao is writing《SpringCloud》.

Using a random number

In some special cases, some parameters we want every time it loads is not a fixed value, such as: key service ports. Spring Boot properties in the configuration file, we can use ${random}to generate a random configuration of an int, long string value or string, so that we can randomly generated easily by configuring the property, rather than in the program by coding enable this logic.

${random}The configurations are mainly about several readers can use as a reference.

# 随机字符串
com.didispace.blog.value=${random.value}
# 随机int
com.didispace.blog.number=${random.int}
# 随机long
com.didispace.blog.bignumber=${random.long}
# 10以内的随机数
com.didispace.blog.test1=${random.int(10)}
# 10-20的随机数
com.didispace.blog.test2=${random.int[10,20]}

This configuration can be used scene settings such as port, avoid the trouble of port conflicts when local debugging

Command line parameters

Recall in the Quick Start chapter, we describe how to start Spring Boot application, which refers to the use of command java -jaras command to start. In addition to the command to start the application, you may also be specified on the command line parameters of the application, such as: java -jar xxx.jar --server.port=8888directly in the command line, setting server.port properties, the other port is set to 8888 to start the application.

At the command line to start Spring Boot application, two consecutive minus sign --is on the application.propertiesproperty values in the identified assignment. So, java -jar xxx.jar --server.port=8888command, equivalent to our application.propertiesadd properties server.port=8888.

To modify the property values ​​from the command line is a very important Spring Boot feature With this feature, in theory, have made use of the property before we start is variable, so the port number or, database connections both mean It may be changed when the application starts, unlike the conventional build Spring applications in different environments by the compiler of Maven Profile. The biggest difference is that in this way Spring Boot, allowing the contents of packaged applications throughout the development, testing and deployment of online, while Maven different Profile of each environment schemes constructed package, its contents are different in nature of. However, if each parameter is required to specify the command line, which is obviously not a good program, so let's look at the configuration if multi-environment in Spring Boot in.

Multi-environment configuration

We develop any application, it usually is applied and the same set of procedures to install several different environments, such as: development, testing, production and so on. In which the address of each database environments, server port, and so the configuration will be different, if frequently must modify the configuration file when packaged as different environments, then it is bound to be a very tedious and error prone task.

For configuring multiple environments, the basic idea of ​​the project to build a variety of tools or frameworks are consistent, distinguished by the configuration package after multiple different environments of the configuration file, and then specify the content needs to be packaged by packaging commands, Spring Boot is no exception , or easier.

In Spring Boot multi environment required to meet the profile name application-{profile}.propertiesformat, which {profile}corresponds to your environmental labeling, such as:

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

As to which specific configuration file is loaded, needed application.propertiesby the file spring.profiles.activeto set the property, whose value corresponds to the profile {profile}values. Such as: spring.profiles.active=testwill load the application-test.propertiesconfiguration file contents.

Here, in a different environment to configure different service port, for example, carry out sample experiments.

  • Create different profiles for each environment application-dev.properties, application-test.properties,application-prod.properties
  • In these three documents are all set different server.portproperties, such as: dev environment is set to 1111, test environment set to 2222, prod environment is set to 3333
  • application.properties set spring.profiles.active=dev, that is default to dev environment settings
  • Different configurations of test load
  • Execution java -jar xxx.jarcan be observed is set to service port 1111, which is the default development environment (dev)
  • Execution java -jar xxx.jar --spring.profiles.active=testcan be observed is set to service port 2222, which is configured test environment (test)
  • Execution java -jar xxx.jar --spring.profiles.active=prodcan be observed is set to service port 3333, which is the configuration of the production environment (prod)

According to the above experiment, may be summarized as follows multi-environment configuration roadmap:

  • application.propertiesConfigure generic content, and set spring.profiles.active=devto the default configuration for the development environment
  • application-{profile}.propertiesConfigured in various different environments content
  • By deactivating the command line to configure different environments

Loading order

In the above example, we will need to use Boot Spring configuration contents are placed in the project, although we have been able to pass spring.profiles.activeor be achieved by Maven multi-environment support. But when our team grew, more and more detailed division of labor later, often we do not need to let developers know the details of the test or build environment, but to the person in charge of each respective environment (QA or operation and maintenance) This information is centrally maintained. So if you still configured in such a way to store content, modify the configuration for different environments will have to acquire engineering content to modify the contents of these configurations, when applying a lot of time becomes very inconvenient. At the same time, the configuration contents are visible to developers, which in itself is also a safety hazard. In this regard, there was now a lot of the external configuration of the content framework and tools that follow will be introduced Spring Cloud Config is one of them, in order to better understand the subsequent loading mechanism Spring Cloud Config, we need the data to Spring Boot loading mechanism files have a certain understanding.

Spring Boot more reasonable order to rewrite the value of each attribute, the use of this more particular load order the following properties:

  1. The parameter passed in the command line.
  2. SPRING_APPLICATION_JSONIn the property. SPRING_APPLICATION_JSONJSON format is configured content in the system environment variables.
  3. java:comp/envIn the JNDIproperty.
  4. Java system properties, can be System.getProperties()obtained content.
  5. Operating system environment variables
  6. By random.*randomly arranged properties
  7. Jar package located outside the current application, for different {profile}environmental profiles, for example: application-{profile}.propertiesor YAMLdefined profiles
  8. Jar package located within the current application, for different {profile}environmental profiles, for example: application-{profile}.propertiesor YAMLdefined profiles
  9. Current application packet located outside the jar application.propertiesand YAMLconfiguration content
  10. Located within the current application of the jar packets application.propertiesand YAMLconfiguration content
  11. In the @Configurationannotation modified class by @PropertySourceannotation attributes defined
  12. Application of default properties, the use of SpringApplication.setDefaultPropertiesdefined content

The above priority order of high to low, the lower the number the higher the priority.

It can be seen where items 7 and 9 are outside the application reads the configuration file from the jar package, therefore, realization of the principle of an external configuration is cut from, instead of the external jar package profile assigned loaded position configuration of the content within. With this realization, our engineering in the configuration becomes very clean and we only need to place the required configuration can be developed locally, you can configure other environments do not care, to be responsible for people to maintain that is compatible with the environment can.

2.x new features

In Spring Boot 2.0 launched in Relaxed Binding 2.0, features the original property is bound to do a lot of improvements to help us more easily loaded and reads the configuration information in the Spring. The following article is said on 2.0 improvements to the configuration of Spring Boot.

Binding Profile

Simple type

In Spring Boot 2.0 in time for loading configuration properties that would be like in addition to the version 1.x when removing special characters are, but also configures all-lowercase matching and loading of the way. Therefore, the following four kinds of configurations are equivalent:

  • properties Format:
spring.jpa.databaseplatform=mysql
spring.jpa.database-platform=mysql
spring.jpa.databasePlatform=mysql
spring.JPA.database_platform=mysql
  • yaml format:
spring:
  jpa:
    databaseplatform: mysql
    database-platform: mysql
    databasePlatform: mysql
    database_platform: mysql

Tips: recommended with all lower -delimiter way to configure, for example:spring.jpa.database-platform=mysql

List type

Use the properties file []to locate the type of list, such as:

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

Also supports comma arranged in a divided manner, with the above configuration is equivalent to the following:

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

Yaml used in the configuration file may be used as follows:

spring:
  my-example:
    url:
      - http://example.com
      - http://spring.io

Also supports comma- way split:

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

Note: In the Spring Boot 2.0 for List type of configuration must be continuous, or will throw an UnboundConfigurationPropertiesExceptionexception, so the following configuration is not allowed:

foo[0]=a
foo[2]=b

In the above-described configuration Spring Boot 1.x is possible, foo[1]because there is no configuration, its value would benull

Map Types

Map type and properties in standard mode yaml as follows:

  • properties Format:
spring.my-example.foo=bar
spring.my-example.hello=world
  • yaml format:
spring:
  my-example:
    foo: bar
    hello: world

Note: If the type of Map contain non-alphanumeric key and -characters need []enclosed, such as:

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

Binding properties of the environment

Simple type

In the environment variables by lower case conversion and .replacement _mapping content profile, such as: the environment variable SPRING_JPA_DATABASEPLATFORM=mysqlconfiguration generated in the configuration file provided spring.jpa.databaseplatform=mysqlthe same effect.

List type

You can not use due to environmental variables [and ]symbols, so use _instead. Any surrounded by underlining number will be considered []in the array. such as:

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

Further, the final digital environment variables and the final end is underlined, the last underline may be omitted, such as the first and third example above is equivalent to the following configuration:

MY_FOO_1 = my.foo[1]
MY_FOO_1_2 = my.foo[1][2]

Binding System Properties

Simple type

File system attributes and the configuration is similar to the removal of the special characters are converted to lowercase and implement binding, for example, the following command line parameters are configured to achieve spring.jpa.databaseplatform=mysqlthe effect of:

-Dspring.jpa.database-platform=mysql
-Dspring.jpa.databasePlatform=mysql
-Dspring.JPA.database_platform=mysql

List type

Binding system properties and also similar binding file attributes, through []to labeling, such as:

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

Similarly, he also supports comma-separated ways, such as:

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

Read attributes

The introduction above the contents of the property in Spring Boot 2.0 bindings, you can see that we can attribute to a variety of different expressions, but if we want to read the property in the application environment Spring time, each property the only name that matches the following rules:

  • By .individual elements separated
  • Finally, a .separate prefix attribute name
  • It must be a letter (az) and numbers (0-9)
  • It must be lowercase letters
  • By hyphens -to separate words
  • The only other characters are allowed [and ]for List index
  • You can not begin with a number

So, if we want to read the configuration file spring.jpa.database-platformconfiguration, you can write:

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

The following is not the way to get spring.jpa.database-platformthe configuration content:

this.environment.containsProperty("spring.jpa.databasePlatform")

Note: Use @Valueto obtain configuration content, we also need such features

The new binding API

It adds new binding API in Spring Boot 2.0 to help us more easily obtain configuration information. Here's an example to help you more easily understand:

Example 1: Simple Type

Consider a configuration disposed in propertes:com.didispace.foo=bar

We create the corresponding configuration class for it:

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

    private String foo;

}

Next, the latest Binderobject will be available to come and collect the configuration information:

@SpringBootApplication
public class Application {

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

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

        // 绑定简单配置
        FooProperties foo = binder.bind("com.didispace", Bindable.of(FooProperties.class)).get();
        System.out.println(foo.getFoo());
    }
}

Examples of two: List type

If the configuration is the List content type it? 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!

For these configurations is still very simple, it can be achieved:

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

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

// 绑定List配置
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);

The sample code

This tutorial supporting warehouse:

If you think this article is good, welcome to Star, Follow support! Your concern is my stick of power!

Related Reading

Guess you like

Origin yq.aliyun.com/articles/705246