SpringBoot study notes two-configuration related

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)

 

 

 

 

Guess you like

Origin blog.csdn.net/Stephanie_1/article/details/86566531