① SpringBoot的配置文件
SpringBoot使用一个全局的配置文件,配置文件名是固定的 :
- application.properties
- application.yml
配置文件的作用 : 修改SpringBoot自动配置的默认值(SpringBoot在底层已经配置好的属性)。
② yml 是什么?
YAML(YAML Ain’t Markup Language)
YAML A Markup Language:是一个标记语言
YAML isn’t Markup Language:不是一个标记语言;
YAML:以数据为中心,比json、xml等更适合做配置文件。
配置例子-更改Tomcat默认端口 :
server:
port:8081
③ YAML语法
YAML使用缩进表示层级关系,缩进时不允许使用Tab键,只允许使用空格。缩进的空格的数目不重要,只要相同层级的元素左侧对齐即可。
YAML支持三种数据结构 :
- 对象 : 键值对的集合;
- 数组 : 一组按次序排列的值;
- 字面量 : 单个的不可分割的值。
语法格式如下 :
k:(空格)v;表示一对键值对,空格必须有。
server:
port: 8082
④ YAML值的写法
一般值有三种类型 : 字面量,即普通的值(数字,字符串,布尔);对象、map(键值对);数组(list set)。
(4.1)字面量
k: v:字面直接来写;
字符串默认不用加上单引号或者双引号;
“”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi";输出:zhangsan 换行 lisi;
”:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’; 输出:zhangsan \n lisi
(4.2)对象、map
k: v:在下一行来写对象的属性和值的关系;注意缩进
对象还是k: v的方式
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 18}
(4.3)数组
用- 值表示数组中的一个元素
pets:
‐ cat
‐ dog
‐ pig
行内写法
pets: [cat,dog,pig]
⑤ 使用yaml为bean赋值
(5.1) 添加依赖
<!‐‐导入配置文件处理器,配置文件进行绑定就会有提示‐‐>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
(5.2)JavaBean
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性
* 和配置文件中相关的配置进行绑定;
* prefix = "person":配置文件中哪个下面的所有属性进行一一映射
*
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
*
*/
@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> lists;
private Dog dog;
//...
}
(5.3)编写yml配置文件
server:
port: 8082
person:
lastName: hello
age: 18
boss: false
birth: 2017/12/12
maps: {k1: v1,k2: 12}
lists:
‐ lisi
‐ zhaoliu
dog:
name: 小狗
age: 12
(5.4)使用SpringBoot 测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbooHelloworldQuickApplicationTests {
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person);
}
}
测试结果如下所示 :
Spring容器中的bean被yml中的配置正确赋值!
⑥ properties配置文件
properties配置文件是以前项目中常用的配置文件,SpringBoot同样保留了该种类型的配置文件。
如下所示,在properties文件中为person赋值:
# idea
person.age=21
person.birth=2018/11/11
person.last-name=小明
person.boss=true
person.dog.name=dog
person.dog.age=1
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
运行测试 :
正常获取到值,但是中文乱码,为什么?
应该项目中都遇到这样的例子,读取properties文件中的中文乱码。以前解决办法就是将properties文件中的中文转换为Unicode形式,如\u822a\u6bcd。或者将其重新编码再解码。
idea中解决方法如下图:
- 将其转换为ASCII,其与Unicode是可以相互转换的。
再次测试:
⑦ @Value为bean赋值
在以前的项目中常用为bean赋值(从properties文件中获取值)的方法有两种:
第一种-xml配置 :
- 示例如下
<bean id="urlModel" class="com.hh.core.model.UrlModel" >
<property name="url" value="${url}"></property>
</bean>
第二种-@Value
@Component
public class Person {
/**
* <bean class="Person">
* <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
* <bean/>
*/
//lastName必须是邮箱格式
// @Email// 不支持JSR303校验
@Value("${person.last-name}")//键必须与properties文件中的一致
private String lastName;
@Value("#{11*2}")//支持SpELl语法
private Integer age;
@Value("true")
private Boolean boss;
private Date birth;
// @Value("${person.maps}")//不支持复杂类型封装
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
//...
}
⑧ @Value获取值和@ConfigurationProperties获取值比较
松散绑定 :
–person.firstName:使用标准方式
–person.first-name:大写用-
–person.first_name:大写用_
–PERSON_FIRST_NAME:
.推荐系统属性使用这种写法
上面几种写法在@ConfigurationProperties环境下都可以对应到person对象的firstName属性。@Value则必须保证取的键与properties文件中一致。
JSR303校验:
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
//lastName必须是邮箱格式
// @Value("${person.last-name}")
@Email
private String lastName;
//...
}
@Value 不支持JSR3030校验,但是支持SpELl语法。@ConfigurationProperties则相反。
对比总结如下:
总结如下:
配置文件yml还是properties他们都能获取到值;
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
那么能否在业务逻辑类中使用@ConfigurationProperties呢?
不建议使用,@ConfigurationProperties会将本类中的所有属性和配置文件中相关的配置进行绑定。尤其@ConfigurationProperties支持松散语法。
⑨ @PropertySource加载指定的配置文件
将一切配置全部写在全局配置文件中,是不可想象的。项目中不可避免存在多个配置文件。@PropertySource就可以根据需要加载指定的配置文件(@ConfigurationProperties 默认从全局配置文件获取配置)。
这里将person的属性配置单独写在person.properties文件中,并从全局配置文件中注释掉person的属性配置。
为了对比person的属性从不同配置文件赋值,这里将全局配置文件中保留person.lastName属姓配置。
测试如下:
分析可知,默认从全局配置文件中为person赋值,这里为lastName赋值小明。person的其他属性从person.properties文件中获取。
⑩ 多个配置文件同属性配置@Value取值
如果项目中不同配置文件中配置同属性,使用@Value该如何取值呢?
如图一:
application.properties与person.properties同时配置了属性person.last-name,如图中所示,使用@Value取值,此时取到的值为application.properties中的值。
若将application.properties中的person.last-name注释掉,则取的为person.properties值。
那么是否说明,默认从全局配置文件取还是按照上次顺序依次检查呢?
如图二所示:
修改application.properties为tapplication.properties文件,将会从application.yml到tapplication.properties依次查找,如找到该属性则取其值。
那么是否说明了配置文件的加载次序呢?参考博客:SpringBoot配置文件加载位置与优先级。
(11)@ImportResource导入Spring配置文件
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别。那么如何使用我们自己编写的配置文件呢?
在主配置类添加@ImportResource注解,如下图:
配置文件内容如下:
<bean id="helloService" class="com.web.service.HelloService"/>
测试如下:
在主配置类使用ImportResource引入自定义Spring配置文件,即可获取helloService bean。
(12)SpringBoot推荐给容器中添加组件的方式
SpringBoot推荐使用配置类的方式来给容器中添加组件。如下所示:
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService helloService(){
System.out.println("配置类@Bean给容器中添加组件了...");
return new HelloService();
}
}
测试结果如下图:
(13)配置文件占位符
除了前面说的几种方式,还可以使用占位符的方式在配置文件中为属性赋值。
① 随机数
示例如下:
person.last‐name=张三${random.uuid}
② 占位符获取之前配置的值,如果没有可以是用:指定默认值
示例如下:
person.last‐name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
${person.hello:hello}
意思为如果person.hello没有值则默认赋值为hello。${person.hello}
如果有值,则取值,无值则会当作字面量解析–${person.hello}原样赋值。