Article Author: Tyan
Blog: noahsnail.com | CSDN | Jane Book 24. External configuration
Spring boot allows you to make an external configuration, so you can run the same application code in a different environment. You can use properties files, YAML files, environment variables, and command line parameters to make an external configuration. Property values can be injected directly into your beans using @value annotations, accessed through spring's environment abstraction or through @configurationproperties binding to a structured object.
Spring Boot uses a very special Propertysource order, which is designed to allow reasonable rewriting of values. The properties are considered to be in the following order: the development tools under the root directory Global Settings property (~/.spring-boot-devtools.properties when the development tool is activated). @testpropertysource annotations in the test. The @springboottest#properties annotation feature in the test. command-line arguments. The attributes in the Spring_application_json (inline JSON embedding in environment variables or system properties). ServletConfig initialization parameters. ServletContext initialization parameters. The jndi nature of the java:comp/env. Java System Properties (System.getproperties ()). Operating system environment variables. Randomvaluepropertysource only has attributes in the random.*. Application properties (Application-{profile}.properties and YAML variables) for the specified configuration file outside the jar package. The application properties (Application-{profile}.properties and YAML variables) for the specified configuration file within the jar package. App properties outside the jar package (application.properties and YAML variables). Application properties within the jar package (application.properties and YAML variables). @propertysource annotations in the @Configuration class. The default property (specified by Springapplication.setdefaultproperties).
To provide a concrete example, suppose you have developed a @component that uses the name attribute:
Import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*
@Component Public
class Mybean {
@Value ("${name}")
private String name;
// ...
}
In your application path (for example, inside your jar), you can use application.properties to provide a reasonable default property value for name. When running in a new environment, application.properties can be supplied outside the jar to override name, and for a one-time test, you can start with the specified command line switch (for example, Java-jar app.jar--name= "Spring").
Spring_application_json can be provided through environment variables at the command line. For example, in a Unix shell:
$ Spring_application_json= ' {"foo": {"bar": "Spam"}} ' Java-jar Myapp.jar
In this example, there will be foo.bar=spam in spring's environment. You can also provide JSON as a spring.application.json in system variables.
$ Java-dspring.application.json= ' {"foo": "Bar"} '-jar Myapp.jar
or command-line arguments:
$ Java-jar Myapp.jar--spring.application.json= ' {"foo": "Bar"} '
or Jndi variable Java:comp/env/spring.application.json 24.1 to configure random values
Randomvaluepropertysource is useful when injecting random values (for example, by injecting a secret or test case). It can produce integers,longs,uuids or strings, for example:
My.secret=${random.value}
My.number=${random.int}
My.bignumber=${random.long}
my.uuid=${ Random.uuid}
My.number.less.than.ten=${random.int (Ten)}
my.number.in.range=${random.int[1024,65536]}
random.int* syntax OPEN value (, max) Close,open,close can be any character, Value,max is an integer. If Max is provided, value is the minimum value and Max is the maximum value (not included). 24.2 Accessing command-line Properties
By default, Springapplication converts any command-line arguments (starting with, for example,--server.port=9000) into a property and adds it to spring's environment. As mentioned earlier, command-line properties always take precedence over other configuration sources.
If you want to add a command line property to environment, you can disable it by using Springapplication.setaddcommandlineproperties (false). 24.3 Apply Properties File
Springapplication loads the properties from the Application.properties file in the following location and adds them to the spring environment:
subdirectory of current directory/config
Current directory
The/config package in Classpath
root directory of the Classpath
This list is sorted by priority (properties in higher positions override attributes defined at lower positions).
You can also use a yaml (. yml) file instead of the. properties file.
If you do not like to use Application.properties as the name of the configuration file, you can change the configuration file name by specifying the Spring.config.name environment property. You can also use the Spring.config.location environment property to refer to an explicit location (directory location or file path separated by commas).
$ Java-jar Myproject.jar--spring.config.name=myproject
Or
$ Java-jar Myproject.jar--spring.config.location=classpath:/default.properties,classpath:/override.properties
Spring.config.name and spring.config.location can be used earlier to decide which file to load, so it must be defined as an environment property (typically an operating system environment, System Properties, or command-line parameters).
If Spring.config.location contains directories (as opposed to files), they should end with a/(before loading, add the names that are generated from Spring.config.name, including the name of the specified configuration file). The file specified in Spring.config.location is used as-is, the specified profile variable is not supported and will be overwritten by the properties of any specified profile.
The default search path is always used classpath:,classpath:/config,file:,file:config/, regardless of the value in Spring.config.location. The search path is sorted from low to high (file:config/highest). If you specify your own location, they take precedence over all default locations and use the same order from low to high. This way you can set a default value for your app in Application.properties (or you can choose the other base name of the Spring.config.name), overwrite it with other files at run time, and keep the default values.
If you use environment variables instead of system attributes, most operating systems do not allow period-delimited keywords, but you can use underscores instead (for example, Spring_config_name instead of spring.config.name).
If you are running in a container, the Jndi attribute (in java:comp/env) or the servlet context initialization parameter can also be used in place of environment variables or system properties. 24.4 specific profile properties
In addition to the Application.properties file, a specific profile property can be defined using the naming convention application-{profile}.properties. Environment has a list of default profiles (default = [defaults]), and if no active profile is set, the default profile is used (for example, if an explicit configuration file is not activated, The properties in the Application-default.properties are loaded).
The specific profile property loads the application.properties from the same location, and the specific profiles always overwrite the non-specific configuration file, whether the specific profile file is inside or outside of the jar you packaged.
If several configuration files are specified, the last one will be applied. For example, the configuration file specified by the Spring.profiles.active property is added by the Springapplication API after those configured files, so the priority is higher.
If you specify any files in Spring.config.location, the specific profile versions of those files will not be considered. If you also want to use a specific profile property, use the directory in Spring.config.location. 24.5 placeholders in attributes
When you use the value in Application.properties, it is filtered through the existing environment, so you can refer to the values defined previously (for example, from System Properties).
App.name=myapp
App.description=${app.name} is a Spring Boot application
You can also use this technique to create an existing short version of the Spring boot property. For more details on how to use, see section 70.4, "Using ' short ' command line arguments". 24.6 using Yaml instead of properties
Yaml is a superset of JSON that can be used to specify hierarchical configuration data in a very convenient form. When your classpath has a snakeyaml library, the Springapplication class automatically supports YAML as a substitute for properties.
If you use ' starters ', Snakeyaml will be provided automatically by Spring-boot-starter. 24.6.1 Loading Yaml
The spring Framework provides two classes for easy loading of YAML documents. Yamlpropertiesfactorybean will load Yaml as Properties,yamlmapfactorybean will load Yaml as a map.
For example, the following YAML document:
Environments:
Dev:
url:http://dev.bar.com
name:developer Setup
prod:
url:http://foo.bar.com
name:my Cool App
will be converted to these attributes:
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
The Yaml list uses [index] to dereference a key represented as a property, such as this yaml:
my:
servers:
-dev.bar.com
-foo.bar.com
will be converted to these attributes:
My.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
To bind these properties like the spring DataBinder (@ConfigurationProperties function), You need to have attributes in the target bean of type java.util.List (or set), you need to provide a setter or initialize it with a mutable value, for example, bind the property value above:
@ConfigurationProperties (prefix= "my") public
class Config {
private list<string> servers = new ArrayList <String> ();
Public list<string> getservers () {
return this.servers;
}
}
24.6.2 exposing Yaml as a property in spring environment
The Yamlpropertysourceloader class can use Yaml as a propertysource in spring's environment. This allows you to access the YAML properties using familiar @value annotations and placeholder syntax. 24.6. More than 3 profiles of YAML documents
You can specify more than one YAML document for a specific profile in a single file, using the Spring.profiles keyword to indicate which document to use when writing the application. For example:
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 example above, if development profile is activated, the value of Server.address is 127.0.0.1. If development and production profile are not available, the value of Server.address is 192.168.1.100.
When the application context is started, the default profile is activated if there is no explicit activation profiles. So in this Yaml file we only set the Security.user.password in the "Default" profile.
Server:
port:8000
---
spring:
profiles:default
Security:
User:
password:weak
In this example, the password is always set because it is not added to how the profile is, and we must reset it explicitly in other profiles if necessary:
Server:
port:8000
Security:
User:
password:weak
Spring Profiles is designed to use the "spring.profiles" element to be selective in the use of! character to negate. If the negative and non-negative profiles point to a single document, it must match at least one non-negative profile, which may not have a negative profile to match. 24.6.4 Yaml Cons
Yaml files cannot be loaded by @propertysource annotations. So in this case if you need to load the value, you need to use the properties file. 24.6.5 Merging Yaml lists
As we have seen above, any YAML content will eventually be converted into attributes. This process can be counterintuitive when overriding the "List" property through profile.
For example, assume that the name and description properties of the Mypojo object are empty by default. Use a Mypojo list from fooproperties:
@ConfigurationProperties ("foo") public
class Fooproperties {
private final list<mypojo> List = new Arraylist<> ();
Public list<mypojo> getList () {
return this.list;
}
}
Consider the following configuration:
Foo:
list:
-name:my name
description:my description
---
spring:
profiles:dev
foo:
list:
-Name:my another name
If Dev profile is not activated, Fooproperties.list will contain a mypojo input defined above. However, if Dev profile is available, lists still contains only one input (name "My another name", description is empty). This configuration will not add a second Mypojo to the list, and it will not be able to merge these items.
When you specify a collection in more than one profiles, the highest-priority set is used (which is the only one):
Foo:
list:
-name:my name
description:my description
-name:another name
Description: Another description
---
spring:
profiles:dev
foo:
list:
-Name:my another name
In the example above, assuming that dev profile is activated, Fooproperties.list will contain a Mypojo input (name "My another name", description is empty). 24.7 Type-Safe configuration Properties
Boot provides an alternative way to handle attributes, allowing strongly typed beans to manage and validate the configuration of your app. For example:
@ConfigurationProperties (prefix= "Connection") public
class ConnectionProperties {
private String username;
Private inetaddress remoteaddress;
... getters and Setters
}
It is recommended to add getters and setters, which are bound through the standard Java Beans Property descriptor, as in spring MVC. They are mandatory for non-mutable types or those types that can be cast directly from a string. As long as they are initialized, maps, collections, or arrays require getter methods, but do not require setter methods because they can be changed directly by binding. If you have a setter, you can create maps, collections, and arrays. Maps and collections can be extended by getter, and array extensions require setters. If they have a default constructor, or if the constructor receives a value that can be cast from a string type, the embedded Pojo property can also be created (so the setter is not mandatory). Some people use the Lombok project to automatically add getter and setter.
Please see the difference between @value and @configurationproperties.
You also need to list the attribute classes to register in the @enableconfigurationproperties annotation:
@Configuration
@EnableConfigurationProperties (connectionproperties.class) public
class Myconfiguration {
}
When @configurationproperties registers in that way, the bean will have a regular name:<prefix>-<fqn>,<prefix> is the prefix for the Environment keyword specified in the @configurationproperties annotation,<fqn> is the full qualified name of the bean. If the annotations do not provide any prefixes, only the full qualified name of the bean is used.
In the example above, the bean name is connection-com.example.connectionproperties, assuming ConnectionProperties is in the Com.example package.
Even if the above configuration creates a regular bean for connectionproperties, we recommend that @configurationproperties only handle the environment, especially not injecting other beans from the context. It has been said that for any bean with @configurationproperties annotations to be configured according to the environment attribute, @EnableConfigurationProperties annotations are automatically applied to your project. Make sure that connectionproperties is already a bean, and you can abbreviate the myconfiguration above:
@Component
@ConfigurationProperties (prefix= "Connection") public
class ConnectionProperties {
//... Getters and Setters
}
This style of configuration works especially well in the Springapplication YAML configuration:
# application.yml
Connection:
username:admin
remoteaddress:192.168.1.1
# Additional configuration As required
To work with @configurationproperties beans, you can inject them in the same way as any other bean:
@Service public
class MyService {
private final connectionproperties connection;
@Autowired public
MyService (connectionproperties connection) {
this.connection = connection;
}
//...
@PostConstruct public
void OpenConnection () {
Server server = new Server ();
This.connection.configure (server);
}
}
Using @configurationproperties also allows you to generate metadata files that Ides can use. For more details, see Appendix B, Configuring the metadata appendix. 24.7.1 Third-party configuration
You can also use @configurationproperties to annotate a class, or you can use it on a public @bean method. This is especially useful when you want to bind properties to third-party components outside of your control.
@ConfigurationProperties (prefix = "foo")
@Bean public
foocomponent foocomponent () {
...
}
Any defined attribute with the Foo prefix will be mapped to the foocomponent bean in the same way as in the connectionproperties example above. 24.7.2 loosely bound
Spring boot uses some loose rules to bind the Environment property to the @configurationproperties beans, so there is no need for an exact match between the Environment property name and the Bean property name. Common useful examples include dashes separated (for example, Context-path bound to ContextPath), case (for example, port bound to port,) environment properties.
For example, given the following @configurationproperties class:
@ConfigurationProperties (prefix= "person") public
class Ownerproperties {
private String firstName;
Public String Getfirstname () {
return this.firstname;
}
public void Setfirstname (String firstName) {
this.firstname = firstName;
}
}
The following property names can be used:
table 24.1. Loosely bound
| Property
Note |
Person.firstname |
The standard hump notation |
Person.first-name |
Dash annotations, recommended for use in. Properties and. yml files |
Person.first_name |
Underline annotations, alternative notation in. Properties and. yml files |
Person_first_name |
Uppercase form. Recommended when using System variables |
24.7.3 Property Conversion
When spring binds a property to @configurationproperties beans, it attempts to cast an externally applied property to the correct type. If you need to customize the type conversion you can provide a conversionservice bean (bean ID of conversionservice), or custom attribute editor (via Customeditorconfigurer Bean), or custom converters (bean definitions with @configurationpropertiesbinding annotations).
Bean requirements are early in the application lifecycle to ensure that the dependencies used by Conversionservice are limited. In general, any dependencies you require may not be fully initialized at the time of creation. If your custom conversionservice does not require the CONFIG keyword to be cast, you may want to rename your custom Conversionservice, And only rely on custom converters that meet @configurationpropertiesbindings. 24.7.4 @ConfigurationProperties Validation
Spring boot attempts to validate the external configuration by default with JSR-303 (if it is in classpath). You can simply add JSR-303 javax.validation constraint annotations to your @configurationproperties class:
@ConfigurationProperties (prefix= "Connection") public
class ConnectionProperties {
@NotNull
private InetAddress remoteaddress;
... getters and Setters
}
In order to validate the embedded property value, you must annotate the relevant field as @valid to trigger its checksum. For example, build on the connectionproperties example above:
@ConfigurationProperties (prefix= "Connection") public
class ConnectionProperties {
@NotNull
@Valid
private remoteaddress remoteaddress;
Getters and setters public
static class Remoteaddress {
@NotEmpty public
String hostname;
... getters and Setters
}
}
By creating a bean definition called configurationpropertiesvalidator, you can also add a custom spring Validator. The @Bean method should declare static. The configuration property validator was created early in the application life cycle, declaring that the @bean method is a static method, allowing the bean to be created without instantiating the @configuration class. This avoids any problems that may arise from early instantiation. Here's an example of a property validation so you can look at how to set it up.
The Spring-boot-actuator module contains an end point that exposes all @configurationproperties beans. Simply point your web browser to/configprops or use the equivalent JMX endpoint. For more details, see Product-level features 24.7.5 @ConfigurationProperties and @value
@Value is a core container feature that cannot provide the same functionality as type-safe configuration properties. The following table summarizes the features supported by @configurationproperties and @value:
function |
@ConfigurationProperties |
@Value |
Loosely bound |
Yes |
No |
Meta Data support |
Yes |
No |
Spel evaluation |
No |
Yes |
If you have defined some configuration keywords for your component, we recommend that you group them into a pojo with @configurationproperties annotations. Also note that @value does not support loose binding, and it is not a good choice if you need to provide a value with an environment variable.
Finally, although you can write an expression in @value, this expression cannot be processed from the application properties file.