[Java] Externalized configuration of spring boot 2.0 features

[Java] Externalized configuration of spring boot 2.0 features

Introduction

Spring boot allows you to externalize its configuration so that you can use the same code in different environments. The configuration can be externalized by using properties, YAML files, environment variables, and named line parameters. The property value can be directly injected into the bean in the form of @value (it is abstracted by spring or is bound to its structured object by using @ConfigurationProperties) spring boot uses a special way that  PropertySourceallows you to override its value and its override order As follows: 1. If the environment variable of devtools is set, it will be used first (it ( ~/.spring-boot-devtools.properties set and activated)) 2. Set @TestPropertySourceon the test class 3. Use @SpringBootTest#properties annotated attributes on the test class 4. Name the line parameter 5. From the SPRING_APPLICATION_JSON property. 6.  ServletConfig Initialization parameters 7.  ServletContext Initialization parameters 8. java:comp/envJNDI properties from . 9. Java system properties (System.getProperties()) 10. Operating system variables 11. Only in System.getProperties()  RandomValuePropertySource . 12. Specify the application attribute external variable attribute ( application-{profile}.properties and YAML variable) configured outside the jar package 13. Specify the application attribute variable ( application-{profile}.properties and YAML variable) in the jar package 14. Application variable specified outside the jar package ( application.properties and YAML variable) 15. Application variables specified in the jar package ( application.properties and YAML variables) 16.  Labels @Configurationused on the  class @PropertySource17. Default attributes (using SpringApplication.setDefaultProperties ) The following is a simple example: assuming that a @Component is developed using the name attribute, the specific code is as follows
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {

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

   //...

} 
In the application root path, you can provide a application.properties designated default environment variable. When running a new environment variable, you can override the value of name by specifying application.properties. For a one-time test, you can send the specified variable through the named line, for example, the code is as follows:
java -jar app.jar --name="Spring " 
You can specify ring SPRING_APPLICATION_JSON environment variables in the linux naming line : the code is as follows:
 SPRING_APPLICATION_JSON='{"acme
                                                            ":{"name ":"test "}}' java -jar myapp.jar 
It can also be done in the following ways:
 java -Dspring.application.json='{"name ":"test "}' -jar myapp.jar 
It can also be in the form of named lines:
java -jar myapp.jar --spring.application.json='{"name ":"test "}' 

Configure random variables

It is RandomValuePropertySource mainly used to inject random variables. It can generate integers, longs, uuids or strings type: as shown in the following code
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]} 
Among them, random.int* can specify the interval range, that is, the interval range between the maximum value and the minimum value.

Link Named Row Properties

By default, SpringApplication the parameters of any named line (the parameters start with "--") will be converted into attributes and added to the spring environment variables. The parameters of the named row always override the parameters of other sources first. If you don't want it to be added to spring's environment variables, you can disable it through the following code:
SpringApplication.setAddCommandLineProperties(false). 

Application properties file

SpringApplication Application.properties will be loaded into the spring environment variables from the following locations:
1. Under the subdirectory/config of the current directory 2. Under the current directory 3. Under/config of the classpath 4. Under the application root directory The above is also the priority order of use . If you don't want to use application.properties as its configuration file name, you can set it by configuring the environment variable spring.config.name. It can also be specified by the environment variable spring.config.location that specifies the location: the following code
#  
java -jar myproject.jar --spring.config.name=myproject
## 
 java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties 
If spring.config.location it also contains a specific directory, you need to use "/".  spring.config.location If the specific configuration environment variable is not supported, it will be replaced by the default configuration environment variable. The order of its configuration search is just the opposite of the order of configuration. For example: the configuration order is: classpath:/,classpath:/config/,file:./,file:./config/, the search order is as follows:
  1. file:./config/
  2. file:./
  3. classpath:/config/
  4. classpath:/
If you configure the spring.config.additional-location property, add it to the default location. The additional position is searched before the default position. For example additional directory for  classpath:/custom-config/,file:./custom-config/which the search order is as follows:
  1. file:./custom-config/
  2. classpath:custom-config/
  3. file:./config/
  4. file:./
  5. classpath:/config/
  6. classpath:/
(Note, we can also configure environment variables in the form of configuration)

Environment-specific configuration attributes (profile-specific)

As an attached application.properties file, profile-specific properties can be defined by using a convenient naming application-{profile}.properties. If no specific environment configuration is activated, its environment variables will adopt a series of default configurations. In other words, if no configuration is activated, the default application.properties file will be used. Profile-specific properties are loaded from standard application.properties by default. Regardless of whether the file specified by its profile-specific is external or internal, it is always loaded.

Placeholders in attributes

We can call the previously defined variables in the unified properties file: the code is as follows:
app.name=MyApp
app.description=${app.name} is a Spring Boot application 

Use YAML instead of attributes

YAML is a super subset of json, which is very convenient to form a hierarchical configuration file. SpringApplication The configuration of YAML is supported by default. yaml is supported by spring-boot-starter by default.
01. Load YAML The spring framework provides 2 ways to load YAML configuration by default, using YamlPropertiesFactoryBean as a property to load YAML and using YamlMapFactoryBean as a MAP to load YAML. For example, the following YAML file
environments:
	dev:
		url: http://dev.example.com
		name: Developer Setup
	prod:
		url: http://another.example.com
		name: My Cool App 
It will be converted to the following attributes:
environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=http://another.example.com
environments.prod.name=My Cool App 
The list of yaml can be applied by {index}: such as the following sub:
my:
servers:
	- dev.example.com
	- another.example.com 
The result after being converted to an attribute is:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com 
When DataBinder binding variables by using  tools, there must be a List class or set on the bound class, and a setter method is provided, as in the following code:
@ConfigurationProperties(prefix="my ")
public class Config {

	private List<String> servers = new ArrayList<String>();

	public List<String> getServers() {
		return this.servers;
	}
} 

02. Exposing yaml attributes in the spring environment is mainly through YamlPropertySourceLoader de-exposing.
03. The yaml document for multiple configuration environments can be specified through spring.profiles which environment variable should be used: the following code
server:
	address: 192.168.1.100
---
spring:
	profiles: development
server:
	address: 127.0.0.1
---
spring:
	profiles: production
server:
	address: 192.168.1.120 
In the above environment, if the development environment is triggered: the server address is: 127.0.0.1, if it is the production address: the address is  192.168.1.120., when neither of them are available, the default is 192.168.1.100. Environment

04. Insufficiency of YAML, it cannot PropertySource be loaded by @
05. Merging YAML lists As mentioned earlier, any yaml will be converted to attributes, and there may be problems when the list is duplicated: the following code
@ConfigurationProperties("acme ")
public class AcmeProperties {

	private final List<MyPojo> list = new ArrayList<>();

	public List<MyPojo> getList() {
		return this.list;
	}

}
-----------------------------------------------
acme:
  list:
    - name: my name
      description: my description
---
spring:
  profiles: dev
acme:
  list:
       - name: my another name 
If it is dev not activated, it contains only one element MyPojo . If it  dev is activated, it still contains only one element. It will not add a second element, and it does not merge its items. When it wants to merge, you must specify a highlight: as shown in the following code:
acme:
  list:
	- name: my name
	  description: my description
	- name: another name
	  description: another description
---
spring:
  profiles: dev
acme:
  list:
	 - name: my another name 
As shown in the first list in the above code
acme:
  list:
	- name: my name
	  description: my description
	- name: another name
	  description: another description
---
spring:
  profiles: dev
acme:
  list:
	 - name: my another name 

Type-safe configuration properties

The use of  @Value("${property} ") injected configuration properties is sometimes cumbersome, especially if there are multiple properties or the data is inherently hierarchical. Spring Boot provides an alternative method: let secure bean management and validator applications: the following example:
 
By using  @EnableConfigurationPropertiesregistered beans:
@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
} 
The above Liezi will be registered as  
@Component
@ConfigurationProperties(prefix="acme ")
public class AcmeProperties {

	//... see the preceding example

} 
This is a very good way for external configuration: the code is as follows:
# application.yml

acme:
	remote-address: 192.168.1.1
	security:
		username: admin
		roles:
		  - USER
		  - ADMIN

# additional configuration as required 
 We can simply use it: as shown in the following code:
@Service
public class MyService {

	private final AcmeProperties properties;

	@Autowired
	public MyService(AcmeProperties properties) {
	    this.properties = properties;
	}

 	//...

	@PostConstruct
	public void openConnection() {
		Server server = new Server(this.properties.getRemoteAddress());
		//...
	}

} 

01. Third-party configuration is the same as using @ConfigurationProperties annotated classes. A public @Bean method can be used . This method is suitable for the property construction of a component of external control. The following code
@ConfigurationProperties(prefix = "another ")
@Bean
public AnotherComponent anotherComponent() {
	...
} 
02. Release binding Spring Boot uses some release rules to bind environment variables to @ConfigurationProperties beans. Therefore, it is not necessary to match the attribute name exactly, as shown below:
@ConfigurationProperties(prefix="acme.my-project.person ")
public class OwnerProperties {

	private String firstName;

	public String getFirstName() {
		return this.firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

} 

03. Attribute conversion spring boot tries to control the type of external attributes and their bound attribute variables to be consistent. If you want to customize the conversion, you can provide a ConversionService service to edit properties or use @ConfigurationPropertiesBinding to customize the converter.
04. @configuration verification @ValidatedSpring boot always verifies @ConfigurationProperties the legitimacy of the  annotated attributes . The javax.validationlegality of the device can be verified through JSR-303  , as shown in the following code:
@ConfigurationProperties(prefix="acme ")
@Validated
public class AcmeProperties {

	@NotNull
	private InetAddress remoteAddress;

	//... getters and setters

} 
In order to trigger the validator, it must be associated with the winning @validate, as shown in the following code:
@ConfigurationProperties(prefix="acme ")
@Validated
public class AcmeProperties {

	@NotNull
	private InetAddress remoteAddress;

	@Valid
	private final Security security = new Security();

	//... getters and setters

	public static class Security {

		@NotEmpty
		public String username;

		//... getters and setters

	}

} 
It can be verified by a custom validator.
05. @configuarationProperties and @value
@value are core embedded properties, which do not provide security configuration properties. The following is @ConfigurationProperties the  @Valuesupport:
characteristic @ConfigurationProperties
@Value
Loose binding yes no
Metadata support yes No
SpEL evaluation
no yes



Remarks: The above documents refer to https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-devtools-globalsettings