maven springboot多環境profile加載不同配置文件自由切換


1.情景展示

  聲明:本文和springboot沒有關系,本質是:maven與spring相互作用產生的效果,之所以標題使用它,是為了讓更多人看到。

  在實際開發過程中,我們經常會有這樣需求:

  開發環境或測試環境,使用測試數據庫;生產環境使用正式數據庫。

  日志級別、引用的jar包、打包方式有時也會不一樣,這樣,同一項目就會存在多個運行環境。

  對於初學者而言,通常的做法就是:

  開發的時候在配置文件使用相關配置信息;需要部署項目的時候,再將原有代碼注釋掉,重新配置一套環境;打完包,在本地調試的時候,再將生產環境配置注銷掉,還原開發環境。

  首先,這種方法肯定是可行的,但經常改來改去,不便維護及拓展。

  下面,介紹一種更好的方案。

2.環境分析

  我們先來了解一下,環境的種類有哪些?

  • 開發環境:development,通常用dev表示;
  • 測試環境:test,通常使用test表示;
  • 預演環境:preview,通常使用prev表示,相當於試運行階段,處於測試和正式階段之間;
  • 生產環境:production,通常使用prod表示。

  基本上上面的4種環境,就涵蓋了我們研發一種產品的所有階段。

  這里,需要說明的是:環境的名稱是可以自定義的,你可以定義成任何名稱,只不過是上面4種是大家約定俗稱的名字而已,無論是誰看到,就能立馬明白什么意思;而如果你將名字定義成aa,也許只有你自己知道它代表的是哪個環境了。

  下面,我先講一種大眾化的多環境開發模式。

  第一,application.properties/yml,作為spring的主配置文件。

  由該配置文件來決定,哪個配置文件生效。

  通過spring.profiles.active來設置生效的配置文件,如上圖所示,我使用的是dev,在啟動項目時,spring會加載application-dev.properties

  第二,設置環境配置文件

   這種方式,很簡單,容易上手,沒什么好說的。

3.解決方案

   這里,介紹一種更為高級的使用方式。

  通過pom.xml的profile標簽來管理環境,換句話說就是:使用maven來完成環境的管理,在使用maven命令進行打包時實現。

  打包形式、打包時是否跳過測試階段、是否啟用接口說明文檔、日志級別、以及引用的jar包,通通由profile來管理,實現在多環境中共存。

  先來看看pom.xml的構成吧,關鍵代碼展示:

<groupId>com.公司簡稱</groupId>
<artifactId>項目名稱</artifactId>
<!--打包形式:通過maven的profile來決定打成war包還是打jar包(如果不配置packaging標簽的話,默認值是jar)-->
<packaging>${project.packaging}</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>項目名稱</name>
<description>項目簡述</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.1.RELEASE</version>
</parent>

<properties>
    <!--指定tomcat內置版本(只對springboot內置tomcat生效)-->
    <!--<tomcat.version>8.5.0</tomcat.version>-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <!--java版本-->
    <java.version>1.8</java.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <!--proguard版本-->
    <proguard.version>6.2.2</proguard.version>
    <!--spring版本號-->
    <spring.version>2.3.1.RELEASE</spring.version>
    <!--打包時是否跳過測試階段(使用profile來指定打包時是否進行測試)-->
    <skipTests>${skipTests}</skipTests>

    <!--加載application-*.yml配置文件(通過該標簽來指定即將生效的配置文件)-->
    <!--加載application-test.yml配置文件(profile需要勾選成test)-->
    <spring.profiles.active>test</spring.profiles.active>
    <!--基層(測試環境)-->
    <!--<spring.profiles.active>jc</spring.profiles.active>-->

    <!--加載application-prod.yml配置文件-->
    <!--這樣,這里就可以根據實際需要,進行多個生產環境間的切換(profile需要勾選成prod)-->
    <!--基層(正式環境)-->
    <!--<spring.profiles.active>jc</spring.profiles.active>-->
</properties>

<!--根據不同的環境引用不同的jar包,最終統一打包到項目當中-->
<!--生產環境:prod,開發環境:dev,測試環境:test,預演環境:prev
使用maven命令打包介紹:
開發環境打包:mvn clean package -Dmaven.test.skip=true -P dev
測試環境打包:mvn clean package -Dmaven.test.skip=true -P test
生產環境打包:mvn clean package -Dmaven.test.skip=true -P prod
!!!另外,在idea中切換生產環境和開發環境時,需要重新導包!!!-->
<profiles>
    <!--開發環境-->
    <profile>
        <id>dev</id>
        <activation>
            <!-- 默認激活本環境 -->
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <!--加載application-dev.yml配置文件(profile需要勾選成dev)-->
            <spring.profiles.active>dev</spring.profiles.active>
            <!--environment這個節點是我自己取的:yml文件根據該標簽的值來確定接口地址是正式地址還是測試地址-->
            <environment>development</environment>
            <!--是否是生產環境:通過配置該值,來決定是否啟用knife4j-->
            <isProduction>false</isProduction>
            <!--日志級別-->
            <logLevel>DEBUG</logLevel>
            <!--打包方式:
                設置成jar包時,在idea中,不能通過插件的package進行打包,
                只能通過命令來實現:mvn clean package -Dmaven.test.skip=true -P dev
            -->
            <project.packaging>jar</project.packaging>
            <!--打包時,需要進行測試-->
            <skipTests>true</skipTests>
        </properties>
        <dependencies>
            <!--jsp不能夠在jar中使用,只能夠在War中使用
            所以,如果確定部署項目的時候以jar的形式運行的話,則項目就不能使用jsp了,
            因為,maven在執行打包命令時,jsp是不會被打包到jar包當中的-->
            <!-- 使用jsp引擎,springboot內置tomcat沒有此依賴 -->
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-jasper</artifactId>
                <version>9.0.36</version>
            </dependency>
            <!--增加對 JSP 文件的支持-->
            <dependency>
                <groupId>org.apache.tomcat</groupId>
                <artifactId>tomcat-jsp-api</artifactId>
                <version>9.0.36</version>
            </dependency>
            <!-- 添加jstl標簽庫依賴模塊 -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
        </dependencies>
    </profile>
    <!--測試環境-->
    <profile>
        <id>test</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <environment>test</environment>
            <isProduction>false</isProduction>
            <logLevel>INFO</logLevel>
            <project.packaging>war</project.packaging>
            <skipTests>true</skipTests>
        </properties>
        <dependencies>
           <!--引用的jar包與生產環境一樣,這里不再展示-->
        </dependencies>
    </profile>
    <!--預演環境-->
    <profile>
        <id>prev</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <environment>preview</environment>
            <isProduction>true</isProduction>
            <logLevel>INFO</logLevel>
            <project.packaging>war</project.packaging>
            <skipTests>true</skipTests>
        </properties>
        <dependencies>
           <!--引用的jar包與生產環境一樣,這里不再展示-->
        </dependencies>
    </profile>
    <!--生產環境-->
    <!--在本地通過Application啟動項目時,其本質還是使用的springboot的內置tomcat,由於內置tomcat不支持使用jsp,
    所以,此時是無法訪問項目對應的jsp頁面的,
    只有將其部署在tomcat上並啟動SpringBootStartApplication才能正常訪問-->
    <profile>
        <id>prod</id>
        <!-- 是否激活本環境 -->
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <environment>production</environment>
            <isProduction>true</isProduction>
            <logLevel>ERROR</logLevel>
            <project.packaging>war</project.packaging>
            <!--打包時,跳過測試階段(因為測試階段會去連接數據庫,正式數據庫本地無法訪問,會導致打包失敗)-->
            <skipTests>true</skipTests>
        </properties>
        <!--項目中,編譯和測試階段用到的jar包,但tomcat中存在這些jar包,此時,在部署到tomcat中時,我們就需要把它們踢掉-->
        <dependencies>
            <!--內置tomcat(剔除該jar包)-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <!--只有編譯和測試階段生效-->
                <scope>provided</scope>
            </dependency>
            <!-- servlet依賴(只在開發時使用,因為部署到tomcat上時,tomcat有對應的jar包) -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <scope>provided</scope>
            </dependency>
            <!-- jstl標簽庫依賴 -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </profile>
</profiles>
<!--配置項目的jar包倉庫-->
<repositories>
    <!--阿里雲倉庫-->
    <repository>
        <id>central</id>
        <name>central maven</name>
        <url>https://maven.aliyun.com/repository/central</url>
        <!--<url>http://maven.aliyun.com/nexus/content/groups/public/</url>-->
    </repository>
    <!--maven官網-->
    <repository>
        <id>public</id>
        <name>public maven</name>
        <url>https://mvnrepository.com</url>
    </repository>
</repositories>
<!--jar包依賴-->
<dependencies>
    <!--公共類封裝引用-->
    <dependency>
        <groupId>code.marydon.encapsulation</groupId>
        <artifactId>javaUtils</artifactId>
        <version>1.0</version>
    </dependency>
</dependencies>

  再來看看application.yml主配置文件

  這里的關鍵點在於:

  yml文件想要引用pom.xml中的property標簽的值時,在要引用的標簽名稱兩邊加上@,即:@propertyName@;如果是properties文件想要引用,使用的是EL表達式,${propertyName}。

  這樣,就將啟用的配置文件的決定權交給了pom.xml。

  提示:

  在idea中,按住Ctrl鍵不松手,會跳轉到對應pom.xml該標簽所處位置。

  knife4j配置(如果沒有,就忽略)

  實現的效果就是:開發環境和測試環境可以訪問接口文檔,預演環境和生產環境禁止訪問。 

  數據庫配置、日志配置等自定義配置不在主配置文件里放,放到對應的環境配置文件當中。

  假設,我們需要調用第三方的接口,而第三方接口也分測試地址和正式地址。

  那我們就可以在這里使用自定義標簽,把正式接口和測試接口添加到配置文件當中。

  如果沒有這種需求,就可以跳過。

 

  這樣,我們分別獲取到當前生效的是哪種環境,測試接口地址,正式接口地址,根據環境來決定最終調用哪個地址。 

  這只是環境的一種使用方式,還有一種應用場景是:根據環境來控制控制層的是否可見(特定請求只在特定環境生效),下篇文章會講。 

  最后,來看看日志。

 

  日志級別,也由pom.xml的profile標簽來決定。

  通常情況下,開發環境使用debug、測試環境使用info,生產環境使用error。

  每種環境的個性化需求,都可以通過這種方式來實現。

  如何正確使用多環境的切換?

  在idea中,想要項目完成環境的切換,至少需要完成前三步,一般項目在清空target目錄后,idea會完成自動編譯,如果沒有那就是你沒有設置自動編譯;

  在idea中,經常會出現因idea自帶的maven插件因環境切換失敗導致項目編譯失敗的問題,這也沒有辦法,是idea自身的問題,重復上述步驟即可。 

  原理就是:maven插件會將yml文件中引用的標簽的值寫入對應的配置文件中。

  補充一點:

 

  如上圖所示,一個地方會產生一個配置文件,而每個地方又可分為生產環境和測試環境,這時候,第一種方式就會顯得力不從心。

  現在,我們只需要三步即可:

  增加一個配置文件,比如叫做:application-aa.yml;

  在pom.xml中,將原有的<spring.profiles.active>注釋掉,添加一個同樣的標簽<spring.profiles.active>aa</spring.profiles.active>;

  選擇要生效的環境,重新編譯項目即可。

  這樣,就實現了多區域多環境可以隨意切換的效果。

寫在最后

  哪位大佬如若發現文章存在紕漏之處或需要補充更多內容,歡迎留言!!!

 相關推薦:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM