SpringBoot configuration file related learning
The following two are global configuration files:
application.properties
application.yml 或 application.yaml
Modify the default value of SpringBoot automatic configuration; the bottom layer will give some automatic configuration, for example, if you want to change the port, you have to modify the configuration file;
YAML YAML Ain't Markup Language concept: a markup language that is yes and no. Very strange
Markup language:
Half of the previous configuration files are xxx.xml files, and YAML is data-centric
The method of yml to modify the port number is shown in the .yml file, as shown below:
Properties method to modify the port number, as shown below:
YAML basic syntax
Basic syntax:
(1) key: value (key space, then colon: write another space, then write value)
(2) The hierarchical relationship is controlled by the indentation of spaces, and the elements with the same width as the left indentation space are the same level configuration
(3) Attributes and values are case sensitive.
The following is the demo:
server:
port : 8081
path : /hello
Value writing
(1) Literal values: ordinary values (numbers, strings, Boolean values) These types of representation methods:
key: Value is written directly as a literal value. The value of string type does not need to be enclosed in single or double quotes.
Double quotes "" and single quotes" have different meanings: strings with double quotes will not be escaped. But when the string is wrapped with single quotes, the special characters are still ordinary characters. For example, a name: "Zhang San\n李四", if double quotation marks are used, the result will wrap, and single quotation marks will output: Zhang San\n李四
(2) Object, Map;
When the value type is an object, key: value write the relationship between the attribute and the value in the next line, but pay attention to the indentation:
For example: in this example, friends is an object, there will be a space between friends and:, first copy and write in strict accordance with the following configuration
firends :
lastName: zhangsan
age: 20
Another inline format for defining object and attribute values:
friends2 : { lastName : zhangsan, age : 20}
(3) Array (List, Set)
The first way of writing, use-value to represent an element in the array, or [] common definition method, the following are two ways of writing:
pets :
- cat
- dog
- pig
pats : [cat, dot, pig]
Configuration file value injection
The following is the yml configuration file of the test, in order to bind the value of the object:
person :
lastName: Zhang San
age : 18
boss : false
birth : 2017/12/12
maps : { key1 : value 1, key2 : 2 }
list :
-Li Si
-King Five
dog :
name: puppy
age : 2
The following is the definition of the Person to be bound:
package com.example.userinitialzr.demo.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**Map each attribute value of the .yml configuration to the java object attribute
@ConfigurationProperties This annotation associates each property in the configuration file with the object property. The value of the prefix parameter determines which configuration value in the configuration file is mapped to.
Only if this component is a component in the Rong flag can it provide the functionality of ConfigurationProperties in the container. @Component identifies this as a container component!
**/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> list;
private Dog dog;
@Override
public String toString() {
return "Person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", birth=" + birth +
", maps=" + maps +
", list=" + list +
", dog=" + dog +
'}';
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getBoss() {
return boss;
}
public void setBoss(Boolean boss) {
this.boss = boss;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
The definition of the child object Dog inside:
package com.example.userinitialzr.demo.bean;
public class Dog {
private String name;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Finally, you can verify from the test class of the default test directory, and print the value of the object to be bound when the project starts, as shown in the following figure:
The figure shows the test result. There is a small green arrow in front of the IDEA class and method names. Right-click to prompt you to run the class or method directly, which is very convenient, as shown in the following figure:
The keyword # of YAML comments is as follows:
#person :
# lastName: Zhang San
Configure the value of person in .properties:
server.port=8081
# Configure the value of person
person.lastName=Zhang San
person.age=12
person.birth=2018/12/24
person.list=a,b,c
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.dog.name=dog
But it should be noted that this configuration method needs to specify the encoding format of the file. When the specified file is running, it can be converted to ASCII code to read Chinese normally, as shown in the following figure:
Pay attention to the writing of attribute binding, the following is some loose syntax:
(1) Standard writing person.firstName
(2) Use-instead of uppercase, that is, person.first-name
(3) Use _ instead of uppercase, that is, person.first_name
(4) It is recommended to write in the system properties at that time: PERSON_FIRST_NAME
Specific demo for data verification: When reading from the configuration file, the following demo demonstrates. Reading the configuration of properties and using @Email annotation to verify whether the data is of the email type, directly obtaining the value of the person property will cause an error , As shown below:
There are three ways to assign values to attributes through @Value:
@Component
@ConfigurationProperties(prefix = "person")
@Validated//Indicates that the field is to be verified
public class Person {
/*
Bean object value mapping method: the first method ${}
*/
@Email //Verify the value through this annotation
@Value("${person.last-name}") //Can only use this way of writing, writing person.lastName will report an error, but all kinds of writing in .properties are supported
private String lastName;
/**
* The second value method #{}, pass an expression in the braces
*/
@Value("#{12*3}")
private Integer age;
/**
* The third value method, direct assignment
*/
@Value("true")
private Boolean boss;
Note: Comparison of Java bean object configuration values (using .properties and @Value methods):
@ConfigurationProperties (that is, the way to write .properties files or .yaml files) |
@Value (annotate directly in front of the properties of the object) |
|
Features |
Bulk injection of properties in configuration files |
Specify the value of the attribute one by one |
Loose binding (loose syntax) |
stand by |
not support |
SpEL (Spring writing, such as #{} expression) |
not support |
stand by |
GSR303 data verification |
stand by |
not support |
Complex type package |
stand by |
not support |
But the same point:
(1) Both ways (configuration file and @Value way) can get the value
In summary, when should the two configuration methods be used?
(1) If you just get a value in the configuration file in a certain business logic, you can use @Value
(2) If you write a java bean (a .java) specifically to handle data mapping, you should use .properties to configure the most complete data
Some keywords of the configuration file:
@PropertySource和@ImportResource
@PropertySource meaning: load the specified configuration file, because the annotation of @ConfigurationProperties reads the global configuration file by default, as shown below:
Usage of the keyword:
@Component
@PropertySource(value = {"classpath:application.properties"}) //Load the specified configuration file so that the bean binds properties from the configuration file
@ConfigurationProperties(prefix = "person") //If there is no @PropertySource annotation before, the global configuration file is read
//@Validated//Indicates that the field is to be verified
public class Person {
/*
Bean object value mapping method: the first method ${}
*/
// @Email //Use this annotation to verify the value
// @Value("${person.last-name}") //Can only be written in this way, writing person.lastName will report an error, but all kinds of writing in .properties are supported
private String lastName;
@ImportProperties Import the configuration file to make the content of the configuration file effective
Useless configuration files in Spring Boot are not effective by default. Mark this annotation on the configuration class to make the configuration file effective
@ImportResource(locations = {"classpath:beans.xml"})
Sping Boot recommends the way to add components to the container: beans.xml is a configuration file I wrote myself, which is the same folder as the default .properties (DemoApplication is my main program class)
package com.example.userinitialzr.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@ImportResource(locations = {"classpath:beans.xml"})//Import the configuration file I wrote
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
The contents of beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--Add a bean component and configure the format of the bean: id: the object name of the bean, class: the package path where the class is located -->
<bean id="helloService2" class="com.example.userinitialzr.demo.service.HelloService"></bean>
</beans>
Test class to test whether the configuration is successfully loaded:
package com.example.userinitialzr.demo;
import com.example.userinitialzr.demo.bean.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
/**
* This is the unit test class of SpringBoot
*
* The function of automatically filling the container can be carried out conveniently during the test
*/
@RunWith(SpringRunner.class) //Use Spring's driver to run. What is the drive do not know
@SpringBootTest //Identify this is a unit test class
public class DemoApplicationTests {
@Autowired
Person person;
@Autowired
ApplicationContext ioc;
@Test
public void contextLoads() {
// System.out.println("yanruTODO person="+person+"@"); //Print to see the value of the bound person object
}
//Determine whether there is HelloService in the container
@Test //Added the @Test annotation, this test function will be run when the class is run
public void testHelloService()
{
boolean b = ioc.containsBean("helloService2");
System.out.println("Does helloService exist?"+b);
}
}
Spring Boot recommended configuration file method: directly use the configuration class to configure the value
package com.example.userinitialzr.demo.config;
import com.example.userinitialzr.demo.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//Specify that the current class is a configuration class.
@Configuration
public class MyAppConfig {
//Add the return value of the method to the container, the default id of this component in the container is the name of the function
@Bean
public HelloService helloServiceYanru()
{
System.out.println("Add components to the container");
return new HelloService();
}
}
Placeholders in configuration files
Random number, as follows ${random.uuid}
The placeholder gets the previously configured value, if not, use: colon to specify the default value, as shown below:
Profile
Function: used to realize Spring Boot flexible choice of production environment or test environment
When the main configuration file is written, the file name can be application-(profile).properties/.yml
The configuration file called by default is the application.properties file
For example, I created two configuration files, the difference lies in the different ports used, as shown in the figure below:
Use the following code in the main configuration file to specify which configuration file to use:
(1) The first method: server.profiles.active=dev (when I configure this locally, I get an error)
server.port=8081
##Specify which configuration file to use
#server.profiles.active=dev
(2) The second way, the command line way:
Specify the system parameters in the project startup item properties: --spring.profiles.active=dev, as shown below:
(3) The way the jar package runs the command line:
java -jar XXX.jar --spring.profiles.active=dev
(4) Virtual machine parameters:
-Dspring.profiles.active=dev
As shown below:
Spring Boot configuration file loading settings
The storage location of the configuration file:
(1)file:.config/
(2)file:./
(3)classpath:/config/
(4)classpath:/
All the configuration files will be loaded in the order of priority from high to low, and the configuration file with high priority will overwrite the configuration file with low priority.
Use spring.config.location to change the location of the configuration file
After the project is packaged, use the form of command line parameters, "hot update" configuration to achieve partial changes to the server:
#Specify the location of the configuration file
spring.config.location=/application.properties
In addition, in addition to the resources in the project, Spring Boot can also load external configuration files, you can view the official instructions in detail.
In addition, when multiple configuration files are loaded at the same time, a complementary configuration state is formed, and the conflicting part will be overwritten by the high-priority configuration file;
When there are profiles with and without profiles at the same time, the profiles with profile will be loaded first.
Specify the parameters when starting the project on the command line:
java -jar D:\MyProjects\SpringBootStudyFromProginn2\demoForConfigLoad\target\demo-0.0.1-SNAPSHOT.jar --spring.context.path=/abc -- server.port=8087
Principle of automatic configuration
For the properties that can be configured in the configuration file, see the Spring Boot official website.
Principle of automatic configuration
(1) The main configuration class is loaded when Spring Boot starts, and the automatic configuration function @EnableAutoConfiguration is turned on
(2) The role of @EnableAutoConfiguration:
Use EnableAutoConfigurationImportSelector to import some components into the container
You can view the contents of the selectImports() method
Get candidate configuration methods:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
Some important function descriptions:
List<String> configurations = SpringFactoriesLoader.loadFactoryNames()
Add all the EnableAutoConfiguration values configured in META-INF/spring.factories under the classpath to the container.
Each XXXAutoConfiguration class is a component in the container, added to the container, through them to achieve automatic configuration
(3) Each automatic configuration class has an automatic configuration function;
(4) Take HttpEncodingAutoConfiguration as an example to explain the principle of automatic configuration:
@Configuration //Indicates that this is a configuration class. Like the configuration files written before, you can also add components to the container
@EnableConfigurationProperties(HttpEncodingProperties.class);//Start the specified class
//ConfigurationProperties function:
@ConditionalOnWebApplication //The function is based on different conditions. If the specified conditions are met, the entire configuration class will take effect. This annotation is to determine whether the current application is a web application. If yes, the configuration takes effect.
@ConditionalOnWClass(CharacterEncodingFilter.class); //Judging whether the current project has this class, CharacterEncodingFilter is a garbled filter
@ConditionalOnProperty(prefix="string.http.encoding", value="enabled" matchIfMissing=true) //Judging whether there is a configuration in the configuration file, string.http.encoding.enabled attribute value, matchIfMissing=true means even Without the .enabled attribute, this configuration also takes effect
public class HttpEncodingAutoConfiguration{
private final HttpEncodingProperties properties;
//When there is only one constructor with parameters, the value of the parameter will be taken from the container
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
@Bean //Add a component to the container, some values of this component need to be obtained from properties
@ConditionalOnMissingBean({CharacterEncodingFilter.class})
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}
(5) All the attributes configured in the configuration file are encapsulated in the XXXProperties class, and what the configuration file can be configured with can refer to the attribute class corresponding to a certain function
Once this configuration class takes effect, this configuration class will add various components to the container;
The essence of Spring Boot:
(1) Sprinig Boot will load the automatic configuration class of the main category;
(2) See if the functions we need have automatic configuration classes written by default in Spring Boot
(3) Let's look at which components are configured in this automatic configuration: as long as the components we want to use are available, there is no need to configure
(4) When adding components to the automatic configuration class in the container, some components will be obtained from the propertie class, and we can specify the values of these properties in the configuration file;
XXXAutoConfiguration automatic configuration class: add components to the container;
The properties required by the package configuration class in xxxProperties
@Conditional derived annotations (the original @Conditional function of the Spring annotation version)
Function: The condition specified by @Conditional must be established before adding a component to the container, otherwise the component will not take effect
For example:
@ConditionalOnJava: Does the Java version meet the requirements?
@ConditionOnMissingBean: Determine whether there is a component in the container, if not, the condition is true
@ConditionalOnProperty: Whether a property is configured in the configuration
and many more
Q: How do we know which auto-configuration classes are in effect?
Specify in the .properties property configuration:
debug=true
When the project is started, the console will print the debug information of the automatic configuration class, so that it is convenient to know which automatic configuration classes are in effect
Keywords in log:
Positive matches: (enabled by the auto configuration class)
Negative matches: (Auto-configuration classes that were not successfully enabled)