1.准備環境
有如下配置文件,yml格式和properties格式
yml格式(經我測試發現,屬性前面的空格兩個不行,需要四個空格才能讀出來,這應該是yml的語法,並且屬性:后面必須有一個空格):
person:
name: 張三
age: 18
birth: 2020/10/1
maps: {k1: v1,k2: v2}
lists:
- item1
- item2
- item3
phone:
os: ios
model: iphone11
price: 9999
properties格式:
person.name= 張三
person.age= 18
person.birth= 2020/10/1
person.maps.k1= v1
person.maps.k2= v1
person.lists= item1,item2,item3
person.phone.os= ios
person.phone.model= iphone11
person.phone.price= 9999
建立與之對應的類,並實現getter、setter和toString
Person類
public class Person {
private String name;
private int age;
private Date birth;
private HashMap<String,Object> maps;
private List<Object> lists;
private Phone phone;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", phone=" + phone +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public HashMap<String, Object> getMaps() {
return maps;
}
public void setMaps(HashMap<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Phone getPhone() {
return phone;
}
public void setPhone(Phone phone) {
this.phone = phone;
}
}
Phone類型:
public class Phone {
private String os;
private String model;
private double price;
@Override
public String toString() {
return "Phone{" +
"os='" + os + '\'' +
", model='" + model + '\'' +
", price=" + price +
'}';
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
2.使用@ConfigurationProperties獲取配置文件
在Person類上面寫注解:@ConfigurationProperties、@Component
@Component: 通過添加 @Component 注解讓 Component Scan 掃描到
@ConfigurationProperties(prefix = "person"): # perfix表示通過指定的前綴,綁定配置文件中的配置
@Component
@ConfigurationProperties(prefix = "person") # perfix表示
public class Person {
}
這里配置完成后idea會有一個小提示:未配置 Spring Boot 配置注釋處理器,此時我們可以將如下配置寫入pom文件的dependencies中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
然后重新生成pom文件運行項目,就可以在配置文件中提示出我們定義的Person類
測試是否配置成功
我們在測試類中進行測試
@SpringBootTest
class ConfigurationDemoApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
運行測試會在控制台中打印出,表示已經配置成功
Person{name='張三', age=18, birth=Thu Oct 01 00:00:00 CST 2020, maps={k1=v1, k2=v2}, lists=[item1, item2, item3], phone=Phone{os='ios', model='iphone11', price=9999.0}}
如果我們使用的配置文件是properties,中文會出現亂碼,如何解決?
打開idea,將透明的原生到 ASCII 轉換勾選上就可以了
3.使用@Value注解獲取配置文件
有如下配置:
@Component
public class Person {
@Value("${person.name}")
private String name;
@Value("#{10*2}")
private int age;
@Value("1999/1/1")
private Date birth;
private HashMap<String,Object> maps;
private List<Object> lists;
private Phone phone;
}
測試結果:
Person{name='張三', age=20, birth=Fri Jan 01 00:00:00 CST 1999, maps=null, lists=null, phone=null}
4.@ConfigurationProperties 和 @Value 獲取值比較
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件的屬性 | 單獨指定 |
松散綁定 | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303數據校驗 | 支持 | 不支持 |
復雜類型(map、list) | 支持 | 不支持 |
松散綁定:
比如綁定person.firstName,配置文件中可以寫:person.firstName、person.first-name、person.first_name、PERSON_FIRST_NAME
SpEL:
#{10*10} 數學計算
#{10>1?"是":"否"} 比較運算
#{field.toString()} 調用方法
#{T(java.lang.Math).PI} 調用靜態方法
JSR303數據校驗:
必須使用@ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email
private String name;
}
@Value相對來說更加靈活,有如下情況,我們只需要person.name
@Value("${person.name}")
private String personName;
@RequestMapping("/hello")
public String index(){
return "hello"+personName;
}
訪問 /hello 可以返回:hello張三
5. 加載指定的配置文件 @PropertySource
有時候我們並不想把某些配置放在全局的配置文件下,比如我們將person配置放在 resource 目錄下:
person.properties
person.name= 李四
person.age= 30
person.birth= 2020/10/1
person.maps.k1= v1
person.maps.k2= v1
person.lists= item1,item2,item3
person.phone.os= ios
person.phone.model= iphone12
person.phone.price= 11111
那么應該如何讀取呢?在配置類上新增:@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
@PropertySource(value = {"classpath:person.properties"})
public class Person {
}
運行測試,控制台打印如下:
Person{name='李四', age=30, birth=Thu Oct 01 00:00:00 CST 2020, maps={k1=v1, k2=v1}, lists=[item1, item2, item3], phone=Phone{os='ios', model='iphone12', price=11111.0}}
6. 通過@ImportResource實現xml配置的裝載,導入Spring的配置文件,讓配置文件里的內容生效
@ImportResource:導入Spring的配置文件,讓配置文件里面的內容生效;SpringBoot所有的bean裝載全部通過java配置實現,那么一直以來習慣的xml配置是否就沒有了用武之地呢,答案是否定的
在項目中增加一個services/HelloService類
在resource目錄下增加一個配置文件
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="com.qingtian.configurationdemo.services.HelloService"></bean>
</beans>
編寫單元測試方法
@Autowired
ApplicationContext context;
@Test
public void testHelloService(){
System.out.println(context.containsBean("helloService"));
}
運行單元測試,控制台打印是:false
SpringBoot中沒有Spring的配置文件,而且我們自己寫的配置文件,也不能自動識別,如何讓配置文件生效呢?
@ImportResource(locations = {"classpath:beans.xml"})
public class ConfigurationDemoApplication {
}
再次運行測試方法,控制台打印:true
SpringBoot不推薦編寫xml配置文件,更推薦使用全注解的方式
編寫我們的配置類 config/MyConfig
@Configuration //指明當前類是一個配置類,就是來代替之前的Spring的配置文件
public class MyConfig {
//將方法的返回值添加到容器中,容器默認的id就是方法名
@Bean
public HelloService helloService(){
return new HelloService();
}
}
7.配置文件中的占位符
RandomValuePropertiSource:配置文件中可以使用隨機數
${random.value} ${random.int} ${random.long} ${random.int(10)} ${random.int[1024,65535]}
屬性配置占位符
app.name=myapp
app.description=${app.name} is a Spring Boot application
-- 可以在配置文件中引用前面配置過的屬性
-- ${app.name:默認值}來指定找不到屬性時的默認值
8.通過Profile配置SpringBoot項目的不同環境
當我們需要在開發、測試、生產系統不斷切換時,如果只有一個配置文件,那會相當的麻煩,使用Profile對不同環境提供不同配置功能,可以通過激活、指定參數等方式快速切換環境
多profile文件形式:
--格式:application-{profile}.properties
- application-dev.properties
- application-prod.properties
多profile文檔塊模式(yml文件支持):
server:
port: 8000
spring:
profiles:
active: dev
---
server:
port: 8001
spring:
profiles: dev
---
server:
port: 80
spring:
profiles: prod
激活方式:
- 命令行 --spring.profiles.active=dev
- 配置文件 spring.profiles.active=dev
- jvm參數 -Dspring.profiles.active=dev
9.配置文件的加載位置
- SpringBoot啟動會掃描以下位置的application.properties或application.yml文件作為SpringBoot的默認配置文件
- file: ./config/
- file: ./
- classpath: /config/
- classpath: /
- 以上是按照 優先級從高到低的順序,所有位置的文件都會被加載,高優先級配置內容會覆蓋低優先級配置內容
- 我們也可以通過配置spring.config.location來改變默認配置
10.外部配置加載順序
SpringBoot支持多種外部配置方式(優先級由高到低)
- 命令行參數
- 來自java:com/env的JNDI屬性
- Java系統屬性(System.getProperties())
- 操作系統環境變量
- RandomValuePropertySource配置的random.*屬性值
- jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
- 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指定的默認屬性