配置文件
1. 配置文件
SpringBoot使用一个全局的配置文件,配置文件名是固定的;
- application.properties
- application.yml
配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;
YAML(YAML Ain’t Markup Language)
- YAML A Markup Language:是一个标记语言
- YAML isn’t Markup Language:不是一个标记语言;
标记语言:以前的配置文件;大多都使用的是 xxxx.xml文件;
YAML:以数据为中心,比json、xml等更适合做配置文件;
YAML:配置例子
server:
port: 8081
properties:配置例子
server.prot=8081
xml:配置例子
<server>
<port>8081</port>
</server>
我们选择yml配置文件方式,添加controller,访问localhost:8081/hello,程序能正常执行
2. YAML基本语法
2.1 基本语法
k: v
:表示一对键值对(空格必须有);
以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的,如下例
server:
port: 8081
path: /hello
属性和值也是大小写敏感
2.2 值的写法
2.2.1 字面量:普通的值(数字,字符串,布尔)
字面值直接来写,字符串默认不加单引号或双引号
- 双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
name: "zhangsan \n lisi"
,输出为zhangsan 换行 lisi
- 单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
name: 'zhangsan \n lisi'
,输出为zhangsan \n lisi
2.2.2 对象、Map(属性和值)(键值对)
对象还是k: v
的方式,在下一行来写对象的属性和值的关系;注意缩进
friends:
lastName: zhangsan
age: 20
行内写法:
friends: {lastName: zhangsan,age: 18}
2.2.3 数组 (List、Set)
用- value
表示数组中的一个元素
pets:
- cat
- dog
- pig
行内写法
pets: [cat,dog,pig]
3. 配置文件注入
步骤一:添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
步骤二:添加实体类
添加一个Person类和一个Dog类
Person类
**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
* prefix = "person":配置文件中哪个下面的所有属性进行一一映射
* 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;所以需要添加@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> lists;
private Dog dog;
//getter、setter、toString()略
}
Dog类
public class Dog {
private String name;
private Integer age;
//getter、setter、toString()略
}
步骤三:编写yaml配置文件
server:
port: 8081
person:
lastName: Jack
age: 18
boss: false
birth: 2019/10/1
maps: {k1: v1,k2: v2}
list:
- lisi
- zhaoliu
dog:
name: Tom
age: 2
步骤四:编写测试方法
@SpringBootTest
class SpringBootHelloworldQuickApplicationTests {
@Autowired
Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
步骤五:运行测试
4. 使用properties配置文件
把yml配置文件里的内容注释掉
在application.properties中添加如下代码
#server.port=8081
#配置person值
person.last-name=张三
person.age=18
person.birth=2019/10/1
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=Tom
person.dog.age=2
properties配置文件默认使用UTF-8编码,需要对其进行转换,否则可能会出现中文乱码,需要在IDEA中做调整
- 修改IDEA配置
- 在properties配置文件中添加编码方式
#server.port=8081
#配置编码方式
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.messages.encoding=UTF-8
#配置person值
person.last-name=张三
person.age=18
person.birth=2019/10/1
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=Tom
person.dog.age=2
5. @Value与@ConfigurationProperties的区别
将实体类中的所有属性和配置文件中相关的配置进行绑定时,除了使用@ConfigurationProperties
,还可以使用@Value
把Person类上方的@ConfigurationProperties注释掉,修改Person类的代码
@Component
//@ConfigurationProperties(prefix = "person")
public class Person {
@Value("${person.last-name}")
private String lastName;
@Value("#{2*9}")
private Integer age;
@Value("#{true}")
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
程序能够正常输出
-
如上所示,@Value支持SpEL,@ConfigurationProperties不支持
-
但是@Value不支持松散绑定,如果按照以下方式书写,程序会出错。
@Value("${person.lastName}")
private String lastName;
在application.properties配置文件中
以下两种方式都支持
person.last-name=张三
person.lastName=张三
故@ConfigurationProperties支持松散绑定
-
@ConfigurationProperties支持JSR303数据校验,@Value不支持
在lastName属性上方添加@Email
,指定lastName必须是email的格式,使用@ConfigurationProperties,程序不会报错,而使用@Value,程序会报错 -
@ConfigurationProperties支持复杂类型封装,@Value不支持
在maps属性上方添加如下代码,程序会报错。@Value不支持Map这种复杂的类型
@Value("${person.maps}")
private Map<String, Object> maps;
- 如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value,如下例
@ResponseBody
@Controller
public class HelloController {
@Value("${person.last-name}")
private String name;
@RequestMapping("/sayHello")
public String sayHello(){
return "hello " + name;
}
}
请求/sayHello,就能获取到properties配置文件中的person.last-name
值
其中@ResponseBody
和@Controller
可以由@RestController
代替
总结如下
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
配置文件yml还是properties他们都能获取到值;
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;
6. @PropertySource & @ImportResource & @Bean
6.1 @PropertySource
在以上几个小节中,我们把所有的配置信息都写在了一个配置文件applicaiton.properties中,但是如果想把有关person的配置信息提取出来,单独写到一个person.properties中,@PropertySource就可以排上用场
首先,新建一个person.properties文件
#配置person值
person.last-name=李四
person.age=18
person.birth=2019/10/1
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=Tom
person.dog.age=2
在Person实体类上方添加注解@PropertySource(value = "classpath:person.properties")
,如下所示
@PropertySource(value = "classpath:person.properties")
@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;
......
运行测试函数,能够读取到配置文件person.properties中的值
6.2 @ImportResource
我们首先在项目中添加一个简单的HelloService
package com.santiago.service;
public class HelloService {
}
再添加一个Spring配置文件beans.xml,把HelloService添加进来,如下所示
<?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="com.santiago.service.HelloService"></bean>
</beans>
添加一个测试类,测试ioc容器中是否包含helloService这个bean
@SpringBootTest
class SpringBootHelloworldQuickApplicationTests {
@Autowired
ApplicationContext ioc;
@Test
void testHelloService(){
boolean b = ioc.containsBean("helloService");
System.out.println(b);
}
}
测试结果为false
,这是因为Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别。
想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上,这里我们将其标注在主配置类上
@ImportResource(value = "classpath:beans.xml")
@SpringBootApplication
public class SpringBootHelloworldQuickApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootHelloworldQuickApplication.class, args);
}
}
加载进来之后,再运行刚才的测试,结果为true
。
6.3 @Bean
6.2中spring配置文件,在SpringBoot中已经不使用了,取而代之的是配置类,推荐使用全注解的方式
首先将@ImportResource注释掉
接着写一个主配置类,当然也可以是主配置类。这里新建一个配置类MyAppConfig
/**
* @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件
*
* 在配置文件中用<bean><bean/>标签添加组件
*
*/
@Configuration
public class MyAppConfig {
//将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名,即id=helloService001
@Bean
public HelloService helloService001(){
return new HelloService();
}
}
@Bean的作用就是将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名
除此之外,不要忘了在配置类上方添加注解**@Configuration**,指明当前类是一个配置类。
运行测试函数
@Test
void testHelloService(){
boolean b = ioc.containsBean("helloService001");
System.out.println(b);
}
结果为true
7. 配置文件占位符
7.1 随机数
可以在配置文件的值中添加一些随机数,如下
${random.value}
、${random.int}
、${random.long}
、${random.int(10)}
、${random.int[1024,65536]}
7.2 使用占位符获取之前配置的值
如果没有可以是用:指定默认值,如下例
修改person.properties文件
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.hello,可以指定默认值为hello,则输出结果为hello_dog
person.dog.age=15
运行测试函数
@Test
void contextLoads() {
System.out.println(person);
}
结果如下
8. Profile
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境
8.1 多Profile文件形式
可以在资源文件夹下新建多个配置文件,指定不同的配置文件适用于不同的开发环境
格式:application-{profile}.properties
或application-{profile}.yml
分别在application.properties、application-dev.properties、application-prod.properties中指定端口号为8081、8082、8083
程序在运行的时候,默认使用的是application.properties,如果想指定其他profile,需要在application.properties添加激活代码spring.profiles.active=dev
8.2 多Profile文档块模式
yaml文件支持文档块模式,只使用一个yaml文件,使用---
分割多个profile区(文档块),就可以实现多个profile,如下所示
server:
port: 8081
spring:
profiles:
active: dev
---
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8083
spring:
profiles: prod
程序运行时默认使用的是第一个文档块,可以在第一个文档块中指定要使用那个profile
8.3 Profile的激活方式
- 配置文件方式:在配置文件中指定 spring.profiles.active=dev
8.1 和 8.2 就是使用的配置文件方式 - 命令行:在配置面板Program arguments中添加命令:
--spring.profiles.active=dev
在dos窗口使用java -jar
命令运行jar包时,可以在其后添加命令--spring.profiles.active=dev
指定运行环境
- jvm参数:
–Dspring.profiles.active=dev
,在配置面板VM Options:一栏中添加参数
9. 配置文件加载位置
spring boot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
file:./config/
file:./
classpath:/config/
classpath:/
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。
如下所示,新建一个项目,用来测试配置文件加载位置,根据以上四个位置,创建同名application.properties
这四个文件分别对server.port=****
赋了不同的值,程序启动时,端口号是根据这四个文件中的值决定的
如果文件1中已经进行了赋值,则后面三个文件中对端口号的配置皆不生效。以此类推,文件4优先级最低。
SpringBoot会从这四个位置全部加载主配置文件;互补配置;如下例
在file:./config/
的配置文件中配置端口号8084
在file:./
的配置文件中不仅配置端口号8081,而且配置项目访问路径
server.port=8081
#配置项目的访问路径
server.servlet.context-path=/boot02
添加controller,配置请求
@RestController
public class HelloController {
@RequestMapping("/hello")
public String sayHello(){
return "hello";
}
}
这四个配置文件形成互补配置,端口号采取file:./config/
文件夹下的,项目访问路径采用file:./
文件夹下的。
则访问hello请求是,请求路径必须为localhost:8084/boot02/hello
- 我们还可以通过spring.config.location来改变默认的配置文件位置,但是这种方式适用于项目打包以后,使用命令行的方式进行配置
例:我们在E盘放置一个application.properties文件,指定server.port=8085
首先先讲项目打包
打包之后的jar包被放置在target目录,我们进入该jar包所在目录,使用命令行的方式运行jar包
注意:程序只将类路径下的文件进行打包,位于项目路路径的文件不打包。file:./config/
和file:./
下的配置文件就不会打包进来。所以运行jar包的时候,jar包里的配置文件只有classpath:/config/application.properties
和 classpath:/application.properties
我们就可以看到端口号已经更改为8085
9. 外部配置文件加载顺序
Spring Boot 支持多种外部配置方式,下列配置方式的优先级从高到低,所有的配置符合互补配置
- 命令行参数
将程序打包后,以java -jar
的方式运行程序,可以在其后跟上命令行参数以修改配置信息
修改多个配置信息需要在参数之间加空格就行了。但是命令行的方式只适用于修改少量配置信息的情况,批量修改配置信息,命令行的方式就不适用了。可以使用第6种方式,在jar包所在文件夹下创建一个application.properties配置文件 - 来自java:comp/env的JNDI属性
- Java系统属性(System.getProperties())
- 操作系统环境变量
- RandomValuePropertySource配置的random.*属性值
- jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
将项目打成jar包后,在jar包所在文件夹下创建一个配置文件application.properties,使用java -jar
的方式运行此jar包,则会读取到该目录下配置文件的配置信息 - jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
- jar包外部的application.properties或application.yml(不带spring.profile)配置文件
- jar包内部的application.properties或application.yml(不带spring.profile)配置文件
- @Configuration注解类上的@PropertySource
- 通过SpringApplication.setDefaultProperties指定的默认属性