目录
Spring Boot配置文件(yml、properties)
Spring Boot配置文件(yml、properties)
Spring Boot提供了两种常用的配置文件,分别是properties文件和yml文件。作用都是修改Spring Boot自动配置的默认值。相对于properties文件而言,yml文件更年轻,也有很多的坑。可谓成也萧何败也萧何,yml通过空格来确定层级关系,使配置文件结构更清晰,但也会因为微不足道的空格而破坏了层级关系
Spring Boot使用一个全局的配置文件,而且配置文件的名字是固定的(两种)
①application.properties(properties中的数据是无序的)
②application.yml(yaml中的数据是有序的)
Spring Boot配置文件的作用是用来修改Spring Boot自动配置的默认值;Spring Boot在底层自动配置好;像Tomcat启动默认配置端口是8080。如果要修改,就在这两个文件的一种中来修改
YAML(YAML Ain’t a Markup Language,不是一种标记语言)
YAML是“YAML Ain’t a Markup Language”(YAML,不是一种标记语言)的递归缩写,使用的是一个递归写法 。在开发的这种语言时,YAML的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)
以前用的配置文件,大多都使用xxxx.xml文件;YAML是一种以数据为中心的配置文件,比json、xml等更适合做配置文件。
yaml和json区别?
没有谁好谁坏,合适才是最好的
配置文件 | 描述 |
---|---|
yaml | 比json优雅,注释更标准,适合做配置文件 |
json | 作为一种机器交换格式比yml强,更适合做api调用的数据交换 |
yaml文件规则
(1)yml文件的好处,天然的树状结构,一目了然,实质上跟properties是差不多的
(2)以空格的缩进程度来控制层级关系。空格的个数并不重要,只要左边空格对齐则视为同一个层级,注意不能用tab代替空格(不支持tab缩进)
(3)大小写敏感
(4)可以使用“-小写字母”或“_小写字母”来代替“大写字母”,如userName与user-name,user_name含义是一样的
key: value 格式书写
key 后面跟着冒号,再后面跟着一个空格,然后是值
以修改端口为例 :
yml:
server:
port: 8081
xml:
<server>
<port>8081</port>
</server>
xml配置将太多的浪费在了标签上面
yaml数据结构
语法:key:(空格)value
表示一对键值对(空格必须有),以(空格)的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的;属性和值也是大小写敏感。
(1)字面量:普通的值(数字,字符串,布尔)
字符串、布尔类型、数值、日期。字符串默认不加引号,单引号会转义特殊字符。日期格式支持yyyy/MM/dd HH:mm:ss
// 字面直接来写,字符串默认不用加上单引号或者双引号
k: v
“”:双引号;不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi"
// 输出:zhangsan 换行 lisi
‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: ‘zhangsan \n lisi’
// 输出:zhangsan \n lisi
(2)对象、Map(属性和值)(键值对)
由键值对组成,形如 key:(空格)value 的数据组成。冒号后面的空格是必须要有的,每组键值对占用一行,且缩进的程度要一致,也可以使用行内写法:{k1: v1, …kn: vn}
// 在下一行来写对象的属性和值的关系;注意缩进
k: v
对象还是k: v的方式
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 18}
(3)数组(List、Set)
由形如 -(空格)value 的数据组成。短横线后面的空格是必须要有的,每组数据占用一行,且缩进的程度要一致,也可以使用行内写法: [1,2,…n]
用 - 值表示数组中的一个元素
pets:
- cat
- dog
- pig
行内写法:
pets: [cat,dog,pig]
(4)复合结构
上面三种数据结构任意组合
Properties(属性文件)
后缀properties是一种属性文件。 这种文件以key=value格式存储内容Java中可以使用Properties类来读取这个文件
String value = properties.getProperty(key)
其语法结构形如:key=value。注意中文乱码问题,需要转码
使用配置文件
1.配置文件
读取配置文件的时候默认读取的是application.properties、application.yml
①yml配置文件内容
user:
id: 1
sname: 张飞
address: 东京
email: www.zhangfei@qq.com
②properties配置文件内容
user.id=1
user.sname=\u5F20\u98DE
user.address=\u4E1C\u4EAC
user.email=www.zhangfei@qq.com
2.配置文件注入
properties、yml读取配置文件一致
(1)@ConfigurationProperties
JavaBean
@Component
@ConfigurationProperties(prefix = "user")
public class User {
private int id;
private String sname;
private String address;
private String email;
// 省略getter/setter方法
}
@ConfigurationProperties(prefix =“person”)
将本类中的所有属性和配置文件中的相关配置进行绑定prefix ="person"表示对哪个文件进行绑定
@Component
表示这是一个容器,只有在容器中ConfigurationProperties才能使用
将配置文件中配置的每一个属性的值,映射到这个组件中@ConfigurationProperties:告诉Spring Boot将本类中的所有属性和配置文件中相关的配置进行绑定;
prefix = “person”:配置文件中哪个下面的所有属性进行一一映射,只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
@ConfigurationProperties(prefix = “person”)默认从全局配置文件中获取值
ConfigurationProperties注解的优缺点
(1)可以从配置文件中批量注入属性;
(2)支持获取复杂的数据类型;
(3)对属性名匹配的要求较低,比如user-name,user_name,userName,USER_NAME都可以取值;
(4)支持JAVA的JSR303数据校验;
(5)缺点是不支持强大的SpEL表达式;
(2)@Value()
JavaBean
public class User {
@value("12") //字面量
private int id;
@value("${user.name}") //从环境变量、配置文件中获取值
private String sname;
@value("${15*1}") //El表达式
private String address;
private String email;
// 省略getter/setter方法
}
@value(“${user.id}”)、${}相当于
<bean class="com.my.beans.User">
<property name="name" value="" />
<bean/>
①字面量:""
②${key}:从环境变量
③#{SpEL}:配置文件中获取值
Value注解的优缺点
(1)只能一个个配置注入值;不支持数组、集合等复杂的数据类型;
(2)不支持数据校验;对属性名匹配有严格的要求。
(3)最大的特点:支持SpEL表达式,使其拥有更丰富的功能
@Value、@ConfigurationProperties获取值比较
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR 303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
不管是配置文件yml还是properties它们都能获取到值;
如果,只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value
如果,专门编写了一个javaBean来和配置文件进行映射,就直接使用@ConfigurationProperties
配置文件占位符
yml与properties配置文件中,都可以使用占位符
随机数
随机数 | 描述 |
---|---|
${random.value} | 类似uuid的随机数,没有"-"连接 |
${random.uuid} | 生成一个uuid,有短杠连接 |
${random.int} | 随机取整型范围内的一个整型 |
${random.int(10)} | 随机生成一个10以内的整型 |
${random.int(100,200)} | 随机生成一个100-200 范围以内的整型 |
${random.long} | 随机取长整型范围内的一个长整型 |
${random.long(100,200)} | 随机生成长整型100-200范围内的一个长整型 |
占位符
语法:${key:defaultValue}。若key不存在,则将defaultValue的值赋值给取值的对象
person.last-name=张三
person.dog.name=${person.last-name:小狗}
输出:张三
person.dog.name=${person.first-name:小狗}
输出:小狗
3.注入测试使用
@ConfigurationProperties,@Value()需要,@Environment不需要
@RunWith(SpringRunner.class)
@SpringBootTest
public class YMLTests {
@AutoWired
private User user;
@Test
public void fun() {//直接运行这个方法 ,而不是运行整个程序
System.out.println(user);
}
}
这个测试得在src/test/java下;项目加载文件的时候属性值才被注入进去,所以可运行项目来测试;也就是启动项目的时候applicaiton.properties/application.yml才被加载
配置文件读取
(1)@Environment
这种方法好像用的比较少,基本没用过
在类中直接注入Environment属性,利用它调用getProperty(“key”),就可以取到值value
@Autowired
private Environment env;
@Test
public void fun() {
System.out.println(env.getProperty("user.name"));
}
(2)PropertiesLoaderUtils
配置文件监听器,来加载自定义配置文件
PropertiesListener.java 用来初始化加载配置文件
// 配置文件监听器,用来加载自定义配置文件
public class PropertiesListener implements ApplicationListener<ApplicationStartedEvent> {
private String propertyFileName;
public PropertiesListener(String propertyFileName) {
this.propertyFileName = propertyFileName;
}
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
PropertiesListenerConfig.loadAllProperties(propertyFileName);
}
}
PropertiesListenerConfig.java加载配置文件内容
public class PropertiesListenerConfig {
public static Map<String, String> propertiesMap = new HashMap<>();
private static void processProperties(Properties props) throws BeansException {
propertiesMap = new HashMap<String, String>();
for (Object key : props.keySet()) {
String keyStr = key.toString();
try {
// PropertiesLoaderUtils的默认编码是ISO-8859-1,在这里转码一下
propertiesMap.put(keyStr, new String(props.getProperty(keyStr).getBytes("ISO-8859-1"), "utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (java.lang.Exception e) {
e.printStackTrace();
}
}
}
public static void loadAllProperties(String propertyFileName) {
try {
Properties properties = PropertiesLoaderUtils.loadAllProperties(propertyFileName);
processProperties(properties);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getProperty(String name) {
return propertiesMap.get(name).toString();
}
public static Map<String, String> getAllProperty() {
return propertiesMap;
}
}
Applaction.java 启动类
通过注册监听器(Listeners
) + PropertiesLoaderUtils
的方式
@SpringBootApplication
public class Springbootone1Application {
public static void main(String[] args) {
// 原本只有这一句:SpringApplication.run(Springbootone1Application.class, args);
SpringApplication application = new SpringApplication(Springbootone1Application.class);
// 第四种方式:注册监听器
application.addListeners(new PropertiesListener("app-config.properties"));
application.run(args);
}
}
Controller
@RequestMapping("/listener")
public Map<String, Object> listener() {
Map<String, Object> map = new HashMap<String, Object>();
map.putAll(PropertiesListenerConfig.getAllProperty());
return map;
}
加载配置文件
(1)@PropertySource(加载指定的配置文件)
注意:@PropertySource注解不支持加载yaml文件,支持properties文件
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "user")
public class User {
private int id;
private String sname;
private String address;
private String email;
// 省略getter/setter方法
}
(2)@ImportResource(导入Spring的配置文件)
让配置文件里面的内容生效;必须标注在类上
@ImportResource(value = {"classpath:applicationContext-dao.xml"})
Spring Boot里面没有Spring的配置文件,自己编写的配置文件,也不能自动识别;
所以想让Spring的配置文件生效,加载进来;就要将@ImportResource标注在一个配置类上
@ImportResource(locations = {“classpath:beans.xml”}):类路径上添加配置类的路径,导入Spring的配置文件让其生效
Spring的配置文件(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">
<bean id="helloService" class="cn.qm.HelloService"></bean>
</beans>
@Bean(给容器中添加组件的方式)
推荐使用全注解的方式
1.配置类@Configuration代替Spring配置文件
2.使用@Bean给容器中添加组件
@Configuration
public class HelloService {
//将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
@Bean
public HelloService helloService02(){
System.out.println("配置类@Bean给容器中添加组件了...");
return new HelloService();
}
}
@Configuration
指明当前类是一个配置类;就是来替代之前的Spring配置文件,在配置文件中用标签添加组件
将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名
Profile
多Profile文件
在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml
profile:可以随便命名,名之后在application.properties中配置就OK了。
Spring Boot默认使用配置文件为application.properties;
1.创建application-dev.properties文件
2.在application.properties配置文件中激活自定义的环境配置文件
server.port=8090 #指定端口号
spring.profiles.active=dev #指定加载文件的profile,也就是-后的名字
配置完成后,也就会加载application-dev.properties/yml,及其默认配置文件
配置spring.profiles.active=dev就可以从application.properties加载到application-dev.properties/ yml文件
yml支持多文档块方式
server:
port: 8081
spring:
profiles:
active: prod #表示当前激活使用哪个环境,此时端口是8084;默认8081
--- #--- 表示环境的分割 ,分成不同的文档块
server:
port: 8083
spring:
profiles: dev
---
server:
port: 8084
spring:
profiles: prod #指定属于哪个环境
配置文件加载位置
Spring Boot启动会扫描以下位置的application.properties或者application.yml文件作为Spring Boot的默认配置文件
文件位置 | 描述 |
---|---|
–file:./config/ | 文件路径config目录—>最高优先级 |
–file:./ | 文件路径根目录—>其次 |
–classpath:/config/ | 类路径config目录—>再其次 |
–classpath:/ | 类路径根目录—>最低优先级 |
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
Spring Boot会从这四个位置全部加载主配置文件:互补配置;还可以通过spring.config.location来改变默认的配置文件位置。
项目打包好以后,可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置
外部配置加载顺序
Spring Boot也可以从以下位置加载配置;优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
1.命令行参数;所有的配置都可以在命令行上进行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
多个配置用空格分开; --配置项=值
2.来自java:comp/env的JNDI属性
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
6.jar包外部的application-{profile}.properties或application-{profile}.yml配置文件(带spring.profile)
7.jar包内部的application-{profile}.properties或application-{profile}.yml配置文件(带spring.profile)
8.jar包外部的application.properties或application.yml配置文件(不带spring.profile)
9.jar包内部的application.properties或application.yml配置文件(不带spring.profile)
由jar包外向jar包内进行寻找,优先加载带profile,再来加载不带profile
10.在应用@Configuration配置类中,用 @PropertySource 注解声明的属性文件
11.通过SpringApplication.setDefaultProperties指定的默认属性
配置文件的默认位置,及执行优先级顺序
首先,当创建一个Spring Boot工程时,默认resources目录下就有一个appliction.properties文件,可以在appliction.properties文件中进行项目配置,但是这个文件并非唯一的文件,在Spring Boot中,一共有4个地方可以存放application.properties文件。
1.当前项目根目录下的config目录下
2.当前项目的根目录下
3.resources目录下的config目录下
4.resources目录下
配置文件默认位置的修改
上面4个位置是默认位置,即Spring Boot启动,默认会从这四个位置按顺序去查找相关属性并加载。但是,这也不是绝对的,也可以在项目启动时自定义配置文件位置
例如:在resources目录下创建一个javaboy目录,目录中存放一个appliction.properties文件,那么正常情况下,当启动Spring Boot项目时,这个配置文件是不会被自动加载的。可以通过spring.config.location来手动的指定配置文件的位置,指定完成后,系统就会自动去该目录下查找application.properties文件
配置文件名问题
对于application.properties而言,不一定非要叫application,但是项目默认是去加载名为application的配置文件,如果文件不叫application也是可以的,但是,需要明确指定配置文件的文件名
方式和指定路径一致,这里的key是spring.config.name
Spring Boot配置文件(yml、properties)总结
(1)Spring Boot 支持两种格式的配置文件,其中YAML的数据结构比properties更清晰
(2)YAML 是专门用来写配置文件的语言,非常简洁和强大
(3)YAML 对空格的要求很严格,且不能用Tab键代替
(4)YAML 通过空格缩进的程度确定层级,冒号后面有空格,短横线后面有空格
(5)ConfigurationProperties注解适合批量注入配置文件中的属性,Value注解适合获取配置文件中的某一项
(6)ConfigurationProperties注解支持数据校验和获取复杂的数据,Value注解支持SpEL表达式