将属性配置文件从.properties变更为.yml,使用yml需要将application.properties文件名称改为application.yml(yaml也可以)
一、yml文件
yml格式文件是官方推荐的配置文件方式
1、格式
properties配置文件是一个:key = value 格式
例子:
server.port=8088
yml配置是梯形缩进格式
例子:
server:
port: 8088
根据层级划分,原来的“.”换成“:”,换行后加空格(不能用tab键)缩进,赋值时在“:”后面加个空格
2、yaml特点
1)yaml是容易阅读的
2)yaml数据对编程语言来说是轻便的
3)yaml匹配原生的数据结构对于敏捷语言
4)yaml有一个支持通用工具的一致模型
5)yaml支持一次处理
6)yaml具有表现力和可扩展性
7)yaml易于实现和使用
3、语法特点
1)大小写敏感
2)通过缩进表示层级关系
3)禁止使用tab缩进,只能使用空格键
4)缩进的空格数目不重要,只要相同层级左对齐即可
5)使用#表示注释
二、创建yml文件
在src/main/resources下建立application.yml
#启动端口
server:
port: 8099
#导入子配置文件
spring:
profiles:
include: model1,model2
#定义acme配置
acme:
remote-address: 192.168.1.1
security:
username: admin
roles:
- USER
- ADMIN
在src/main/resources下建立application-model1.yml
model1:
name: model1
在src/main/resources下建立application-model2.yml
model2:
name: model2
子配置文件名用application + “-” + name格式拼接
三、属性注入
发现springboot读取yml配置文件,不需要配置或者只要很简单的配置
1、使用@Value注解
@Value("${model1.name}")
private String str1;
2、使用@ConfigurationProperties注解
@ConfigurationProperties支持全量注入
全量注入的好处就是,当有一类配置很多的时候,可以写在一个class里,一次性都获取
3、增加com.example.properties包
在该包下增加AcmeProperties.java:
package com.example.properties;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "acme")
public class AcmeProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public InetAddress getRemoteAddress() {
return remoteAddress;
}
public void setRemoteAddress(InetAddress remoteAddress) {
this.remoteAddress = remoteAddress;
}
public Security getSecurity() {
return security;
}
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
}
}
4、在src/test/java下增加测试类YamlTest.java
package myboot;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.example.myboot.MybootApplication;
import com.example.properties.AcmeProperties;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MybootApplication.class)
public class YamlTest {
@Value("${model1.name}")
private String str1;
@Value("${model2.name}")
private String str2;
@Autowired
private AcmeProperties acmeProperties;
@Test
public void testYaml() {
System.out.println("model1.name: " + str1);
System.out.println("model2.name: " + str2);
System.out.println("acme.address: " + acmeProperties.getRemoteAddress());
System.out.println("acme.password: " + acmeProperties.getSecurity().getPassword());
System.out.println("acme.username: " + acmeProperties.getSecurity().getUsername());
}
}
四、启动扫描类
springboot启动类的默认扫描路径是该类所在的包下面的所有java类,在启动类所在包下加了@Component注解的类,不需要任何配置就能扫描到
但是如果不在同一个路径,需要在MybootApplication.java上增加指定扫描包路径:
@ComponentScan(basePackages = {"com.example"})
五、执行测试方法testYaml
13:57:13.960 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class myboot.YamlTest]
13:57:13.963 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
13:57:13.970 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
13:57:13.986 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [myboot.YamlTest] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
13:57:13.997 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [myboot.YamlTest], using SpringBootContextLoader
13:57:13.999 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [myboot.YamlTest]: class path resource [myboot/YamlTest-context.xml] does not exist
13:57:14.000 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [myboot.YamlTest]: class path resource [myboot/YamlTestContext.groovy] does not exist
13:57:14.000 [main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [myboot.YamlTest]: no resource found for suffixes {-context.xml, Context.groovy}.
13:57:14.039 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [myboot.YamlTest]
13:57:14.136 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [myboot.YamlTest]: using defaults.
13:57:14.137 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
13:57:14.145 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
13:57:14.146 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
13:57:14.146 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@6ab7a896, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@327b636c, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@45dd4eda, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@60611244, org.springframework.test.context.support.DirtiesContextTestExecutionListener@3745e5c6, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@5e4c8041, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@71c8becc, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@19d37183, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@1a0dcaa, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@3bd40a57]
13:57:14.147 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [myboot.YamlTest]
13:57:14.148 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [myboot.YamlTest]
13:57:14.149 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [myboot.YamlTest]
13:57:14.149 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [myboot.YamlTest]
13:57:14.156 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [myboot.YamlTest]
13:57:14.156 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [myboot.YamlTest]
13:57:14.157 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [myboot.YamlTest]
13:57:14.157 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [myboot.YamlTest]
13:57:14.157 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [myboot.YamlTest]
13:57:14.157 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [myboot.YamlTest]
13:57:14.160 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@7f1302d6 testClass = YamlTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@43ee72e6 testClass = YamlTest, locations = '{}', classes = '{class com.example.myboot.MybootApplication, class com.example.myboot.MybootApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7e0b0338, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@60c6f5b, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@6b09bb57, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@65e2dbf3], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true]], class annotated with @DirtiesContext [false] with mode [null].
13:57:14.161 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [myboot.YamlTest]
13:57:14.162 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [myboot.YamlTest]
13:57:14.180 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=-1}
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.8.RELEASE)
2019-10-09 13:57:14.474 INFO 8204 --- [ main] myboot.YamlTest : Starting YamlTest on DESKTOP-PB5DAU8 with PID 8204 (started by User in D:\workspace\study\myboot)
2019-10-09 13:57:14.475 INFO 8204 --- [ main] myboot.YamlTest : The following profiles are active: model1,model2
2019-10-09 13:57:15.641 INFO 8204 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-10-09 13:57:15.790 WARN 8204 --- [ main] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
2019-10-09 13:57:15.956 INFO 8204 --- [ main] myboot.YamlTest : Started YamlTest in 1.768 seconds (JVM running for 2.312)
model1.name: model1
model2.name: model2
acme.address: /192.168.1.1
acme.password: null
acme.username: admin
2019-10-09 13:57:16.146 INFO 8204 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
六、注解说明
1、@ComponentScan
配置组件扫描路径,搭配@Configuration类使用,提供的支持对应Spring XML的<context:component-scan>
2、@PropertySource
为spring环境添加配置文件路径
用法;@PropertySource("classpath:/com/myco/app.properties")
注:只能添加.properties文件,不能添加yml文件
4、@TestPropertySource
功能同@PropertySource,在测试代码中使用
5、@ConfigurationProperties
原意是为@Configuration注解的类注入属性,支持全量注入
七、参考资料
yaml文件官方文档:https://yaml.org/spec/1.2/spec.html
spring5官方文档:https://docs.spring.io/spring/docs/current/javadoc-api/overview-summary.html
注:最新代码上传至https://github.com/csj50/myboot