SpringBoot——多文件配置

SpringBoot: 2.2.1.RELEASE

IDE: IDEA

使用模塊爲WEB模塊和測試模塊

在軟件開發中我們需要配置許多的配置文件,例如通過配置文件給某些對象初始化,比如利用 @ConfigurationProperties 給對象注入值,但是在默認的情況下我們的配置文件都是 classpath 路徑下的 application.properties 我們不可能所有的信息都保存在這個文件裏,於是我們就要有目的的讀取我們的配置文件。

一 、@PropertySource 和 @ImportResource

1、@PropertySource

在我們使用**@ConfigurationProperties** 獲取注入值時,springboot 默認是 classpath 路徑下的 application.properties 文件,我們可以通過@PropertySource註解來切換注入文件的位置,舉例:

@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean student;
    private Date birth;

    private Map<String,Object> maps;
    private List<Object> lists;

    private School school;
    // getter 、setter 和toString省略
}

我們在classpath 路徑下創建person.properties文件

person.name=黎明
person.age=12
person.student=true
person.birth-date=2019/11/14
person.maps.k1=v1
person.maps.k2=v2
person.lists=list1,list2
person.school.name=曙光
person.school.start-date=2019/09/01

運行測試類

@SpringBootTest
class DemoApplicationTests {
    @Autowired
    Person person;

    @Test
    void contextLoads() {
        System.out.println(person);
    }
}

結果

Person{name='黎明', age=12, student=true, birthDate=Thu Nov 14 00:00:00 GMT+08:00 2019, maps={k1=v1, k2=v2}, lists=[list1, list2], school=School{name='曙光', startDate=Sun Sep 01 00:00:00 GMT+08:00 2019}}

但是我們改成yml文件時就不可以了

person:
  name: Li Ming
  age: 12
  student: true
  birth: 2019/11/14
  maps: {k1: v1,k2: v2}
  lists: [list1,list2]
  school:
    name: shuguang
    start-date: 2019/09/01
@PropertySource(value = {"classpath:person.yml"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean student;
    private Date birth;

    private Map<String,Object> maps;
    private List<Object> lists;

    private School school;
    // getter 、setter 和toString省略
}

結果

Person{name='null', age=null, student=null, birthDate=null, maps=null, lists=null, school=null}

我們發現配置文件裏的值是注入不進來的,所以,這個註解只對properties 文件好使

2、@ImportResource

在以前我們手動將bean添加到ioc容器中我們一般需要寫一個類,再將整個類配置在bean文件中,下面我們試一下

我們創建一個類

public class HelloService {}

將這個類配置到bean文件裏

<?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.demo.services.HelloService"></bean>
</beans>

我們創建測試方法,看看ioc容器中是否存在這個bean

//注入iOC容器
@Autowired
ApplicationContext ioc;
@Test
void contextLoads2() {
    //判斷ioc容器是否存在helloService的bean
    System.out.println(ioc.containsBean("helloService"));
}

運行結果

false

我們發現並不能將這個bean添加到我們的容器中

下面我們通過添加@ImportResource來實現bean的添加

我們將這個註解添加在主方法上

@ImportResource(value = {"classpath:beans.xml"})
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

這樣把beams.xml添加進行,就可以讀到這個文件了

運行結果

true

我們可以知道這個bean添加到容器中了;

當然我們還有一個方法來實現這個功能;

3、@Configuration

首先我們需要創建一個配置類

/**
 * @Configuration 告訴springBoot這是一個配置類相等於bean.xml文件
 */
@Configuration
public class MyBeanConfig {
    /**
     * @Bean 這是告訴springBoot它的返回值就是一個bean,它的id就是這個函數名稱
     * @return
     */
    @Bean
    HelloService helloService2(){
        return new HelloService();
    }
}

修改一下我們的測試方法

//注入iOC容器
    @Autowired
    ApplicationContext ioc;
    @Test
    void contextLoads2() {
        //判斷ioc容器是否存在helloService的bean
        System.out.println("helloService是否存在:"+ ioc.containsBean("helloService"));
        System.out.println("helloService2是否存在:"+ ioc.containsBean("helloService2"));
    }

結果

helloService是否存在:false
helloService2是否存在:true

我們可以知道這種方式我們將 HelloService 添加到容器中了,它的id是函數名稱。

二 、Profile的使用

在項目開發中我們會有許多的環境,在這些環境裏我們一般會有不同的配置文件,如何控制使用不同的配置文件,我們一般通過profile的使用來控制

他的格式是由文件名稱來表明的,文件名稱一般是 application-[profile].yml/properties ,下面我們創建一個

application-dev.yml和一個application-prod.yml

application-dev.yml:

server:
  port: 8081

application-prod.yml:

server:
  port: 8082

我們測試第一個:

application.yml:

server:
  port: 8080
spring:
  profiles:
    active: dev

運行結果

The following profiles are active: dev
Tomcat initialized with port(s): 8081 (http)

測試第二個

application.yml:

server:
  port: 8080
spring:
  profiles:
    active: prod

運行結果:

The following profiles are active: prod
Tomcat initialized with port(s): 8082 (http)

從運行結果上看,我們知道這些文件的配置是生效的,application.yml的配置會被自己調用的配置文件覆蓋掉,從生效端口就可以看出來

三 、配置文件的加載順序

對於配置文件的使用是非常靈活的,用好配置文件對運維有莫大的好處,所以我們要知道文件的優先級,我們以application.yml文件爲例,他的優先級從高到低如下面所示,高優先級會覆蓋低優先級的配置項,爲什麼這麼說,這裏還有一個關鍵詞就是互補配置,就是相同的配置項高優先級覆蓋低優先級,不同的,無論高低都生效

  • file/config/配置文件
  • file/配置文件
  • classpath/config/配置文件
  • classpath/配置文件

現在我們在這四個位置創建這四個配置文件

在這裏插入圖片描述

上面四個文件都是空的,下面一個一個配置

首先從低到高,先配置4號文件

server:
  port: 8081

運行結果

Tomcat initialized with port(s): 8081 (http)

配置3號文件

server:
  port: 8082

運行結果

Tomcat initialized with port(s): 8082 (http)

配置2號文件

server:
  port: 8083

運行結果

Tomcat initialized with port(s): 8083 (http)

配置1號文件

server:
  port: 8084

運行結果

Tomcat initialized with port(s): 8084 (http)

上面的運行結果可以瞭解到他們的順序是生效的,下面我們瞭解一下什麼是互補,

在現在的基礎上我們修改優先級最低的4號文件,創建一個profile文件application-dev.yml

server:
  port: 8085

運行結果

The following profiles are active: dev
Tomcat initialized with port(s): 8085 (http)

從這裏可以看出,4號文件的第二項配置生效了,同時啓用了profile文件,從這裏可以看出profile文件的優先級高於application文件;

四 、配置位置優先級

說完了同名文件加載位置的優先級,現在說一下不同位置,相同配置命令的優先級,

首先我們看一下開發模式下的命令優先級在我們現在已有的基礎上繼續配置

如下:在編輯器的運行配置裏有兩個配置VM optionsProgram arguments 這兩個,首先我們用VM options來運行

命令:-Dserver.port=8086記住命令要加 D

在這裏插入圖片描述

運行結果

The following profiles are active: dev
Tomcat initialized with port(s): 8086 (http)

由上面可以知道profile文件的配置被它覆蓋了;

下面再這個基礎上再加配置,使用Program arguments

命令:--server.port=8087記住命令前是兩個橫槓

在這裏插入圖片描述

運行結果

The following profiles are active: dev
Tomcat initialized with port(s): 8087 (http)

我們可以看到VM options的配置被Program arguments 覆蓋了,由這裏我們大致可以總結開發環境下的配置,上述幾種方法的優先級順序,從從高到底:

  • Program arguments
  • VM options
  • profile文件
  • 全局配置文件application

上面介紹了開發環境的,下面介紹一下部署環境的配置,首先我們需要創建一個配置文件在隨便一個目錄下,不在項目文件就可以,我放在項目的根目錄下;

server.port=8088

我們用命令行的方式運行

命令如下:

demo2\target>java -jar demo2-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties

運行結果

Tomcat initialized with port(s): 8088 (http)

我們發現可以直接調用外部文件

下面我們在用一個命令

demo2\target>java -jar demo2-0.0.1-SNAPSHOT.jar --server.port=8089

結果如下

Tomcat initialized with port(s): 8089 (http)

現在我們綜合使用

demo2\target>java -jar demo2-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties --server.port=8089

結果如下

Tomcat initialized with port(s): 8089 (http)

由上面可得,命令行高於上面所有。

當然具體的要看官方文檔 文檔第四章有一節 Externalized Configuration 有具體介紹

  1. 當devtools處於活動狀態時,$ HOME / .config / spring-boot文件夾中的Devtools全局設置屬性。
  2. 測試上的@TestPropertySource批註。
  3. 測試中的properties屬性。在@SpringBootTest和測試註釋上可用,用於測試應用程序的特定部分。
  4. 命令行參數。
  5. 來自SPRING_APPLICATION_JSON的屬性(嵌入在環境變量或系統屬性中的嵌入式JSON)。
  6. ServletConfig的初始化參數。
  7. ServletContext的初始化參數。
  8. 來自Java:comp / env的JNDI屬性。
  9. Java系統屬性(System.getProperties())。
  10. 操作系統環境變量。
  11. 一個RandomValuePropertySource,僅具有random。*屬性。
  12. 打包的jar之外的特定於配置文件的應用程序屬性(application- {profile} .properties和YAML變體)。
  13. 打包在jar中的特定於配置文件的應用程序屬性(application- {profile} .properties和YAML變體)。
  14. 打包的jar之外的應用程序屬性(application.properties和YAML變體)。
  15. 打包在jar中的應用程序屬性(application.properties和YAML變體)。
  16. @Configuration類上的@PropertySource批註。
  17. 默認屬性(通過設置SpringApplication.setDefaultProperties指定)。

一般常用的就就這幾種了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章