天天看點

hualinux spring 4.16:@Profile 切換環境

目錄

​​一、@Profile 環境切換​​

​​二、例子​​

​​2.1 安裝例子所用的依賴​​

​​2.2 例1 資料庫配置檔案的讀取​​

​​2.2.1 目錄結構​​

​​2.2.2 實作代碼​​

​​2.3 例2 在例1基礎加添加@Profile 注解​​

​​2.3.1 修改配置檔案​​

​​2.3.2 使用 @Profile("default")指定預設環境​​

​​2.3.3 使用  -Dspring-prfofiles.active 激活指定環境​​

​​2.4 使用環境​​

一般公司開發環境分為3種:開發環境dev、測試環境test、生産環境prod

開發環境dev:一般是開發本地進行開發

測試環境test:一般是在公司測試伺服器進行測試

生産環境prod:直接線上上跑,産生收入的,即給客戶使用的

在開發的時候代碼往往根據根據不同的環境進行資料庫切換,這樣我可以配置3套環境的資料庫配置,在不同環境上跑我就指定不同的配置即可,那怎麼做到呢?這就用到了今天的主角@Profile

一、@Profile 環境切換

/**

* Profile:

*      Spring為我們提供的可以根據目前環境,動态的激活和切換一系列元件的功能;

*

* 開發環境、測試環境、生産環境;

* 資料源:(/A)(/B)(/C)

*

* @Profile:指定元件在哪個環境的情況下才能被注冊到容器中,不指定,任何環境下都能注冊這個元件

*   1)加了環境辨別的bean,隻有這個環境被激活的時候才能注冊到容器中。預設是default環境

*   2)寫在配置類上,隻有是指定的環境的時候,整個配置類裡面的所有配置才能開始生效

*   3)沒有标注環境辨別的bean,在任何環境下都是加載的。

* */

二、例子

2.1 安裝例子所用的依賴

本章所有的例子都在使用上一章《hualinux spring 4.15:spring添加maven支援 10分鐘學會mavne》所建立的項目基礎上安裝的

安裝軟體都用maven安裝了,不用直接下載下傳jar包放在項目的lib目錄中,讓maven代為管理。

這個例子中需要用到3個jar包

c3p0:主要是讀取外部配置檔案,一般資料庫配置檔案放在外部,我這裡使用yml方式

mchange-commons-java:c3p0資料庫連接配接池的輔助包

mysql-connector-java:jdbc驅動包,是java連接配接mysql資料庫使用的,我這裡隻是配置檔案,并沒用到mysql資料庫

使用maven之後,我直接用單元測試進行測試了,不使用傳統的Main入口函數運作了,是以還需要安裝一個junit單元測試包,idea支援junit5

上面4種包的可以去​​maven官網​​ 搜尋得到相關的版本和maven安裝的配置檔案,我使用目前它們的最新版本,分别複制,粘貼進idea的pom.xml的<dependencies></dependencies>标簽中,即可,複制完後的pom.xml配置檔案如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hualinux</groupId>
    <artifactId>spring-annotation2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.mchange/mchange-commons-java -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>mchange-commons-java</artifactId>
            <version>0.2.20</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>
        <!-- JUnit5:單元測試需要用到-->
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.6.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>14.0.1</source>
                    <target>14.0.1</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>      

 然後點pom.xml右邊的更新即會自動下載下傳安裝

hualinux spring 4.16:@Profile 切換環境

安裝後之後,不會出現紅色字型,表示全部正常

ps:本章所有例子的pom.xml 配置都不會變

2.2 例1 資料庫配置檔案的讀取

2.2.1 目錄結構

hualinux spring 4.16:@Profile 切換環境

db.yml:mysql資料庫配置檔案,maven規定要放奪resources目錄中,不能放其它地方

com.hualinux.conf.MainConfProfile.java:這個為資料庫配置檔案

IOCTest_Profile.java:這個java檔案我放在test目錄下,表示這個是一個測試檔案,我使用的是junit5單元測試,這個也很簡單的,講一下就懂了

2.2.2 實作代碼

db.yml内容如下:

user: root
pwd: root
driverClass: com.mysql.cj.jdbc.Driver
jdbcUrlTest: jdbc:mysql://127.0.0.1:3306/hua_test?serverTimezone=GMT%2B8
jdbcUrlDev: jdbc:mysql://127.0.0.1:3306/hua_dev?serverTimezone=GMT%2B8
jdbcUrlProd: jdbc:mysql://127.0.0.1:3306/hua?serverTimezone=GMT%2B8      

注意:

1.那個冒号後面有一個空格的!而且這個空格是不能省的,省會出讀不到資料。

2.值不能用雙引号或單引号,引起來,否則連接配接資料庫會有問題,下面是錯誤的寫法

#值不能用單引号或雙引号,否則會出問題,下面寫法是錯誤的

driverClass: "com.mysql.cj.jdbc.Driver"

jdbcUrlTest: "jdbc:mysql://127.0.0.1:3306/hua_test?serverTimezone=GMT%2B8"

jdbcUrlDev: "jdbc:mysql://127.0.0.1:3306/hua_dev?serverTimezone=GMT%2B8"

jdbcUrlProd: "jdbc:mysql://127.0.0.1:3306/hua?serverTimezone=GMT%2B8"

com.hualinux.conf.MainConfProfile.java代碼如下:

package com.hualinux.conf;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;

@PropertySource(value={"classpath:/db.yml"})
@Configuration
public class MainConfProfile {

    @Value("${user}")
    private String user;
    @Value("${pwd}")
    private String pwd;
    @Value("${driverClass}")
    private String driverClass;
    @Value("${jdbcUrlTest}")
    private String jdbcUrlTest;
    @Value("${jdbcUrlDev}")
    private String jdbcUrlDev;
    @Value("${jdbcUrlProd}")
    private String jdbcUrlProd;


    @Bean("testDataSource")
    public DataSource dataSourceTest() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setDriverClass(driverClass);
        //測試環境使用的資料庫
        dataSource.setJdbcUrl(jdbcUrlTest);
        return dataSource;
    }

    @Bean("devDataSource")
    public DataSource dataSourceDev() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setDriverClass(driverClass);
        //開發環境使用的資料庫
        dataSource.setJdbcUrl(jdbcUrlDev);
        return dataSource;
    }


    @Bean("prodDataSource")
    public DataSource dataSourceProd() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setDriverClass(driverClass);
        //生産環境使用的資料庫
        dataSource.setJdbcUrl(jdbcUrlProd);
        return dataSource;
    }


}      

test-->java-->IOCTest_Profile.java

import com.hualinux.conf.MainConfProfile;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.sql.DataSource;

public class IOCTest_Profile {

    AnnotationConfigApplicationContext ctx;

    @Test
    //注意test不能有傳回值隻能是void
    public void test01(){
        ctx=new AnnotationConfigApplicationContext(MainConfProfile.class);
        String[] namesForType = ctx.getBeanNamesForType(DataSource.class);
        for (String name: namesForType){
            System.out.println(name);
            ComboPooledDataSource dataSource= (ComboPooledDataSource) ctx.getBean(name);
            System.out.println(dataSource.getJdbcUrl());
        }
        ctx.close();
    }

}      

ps:測試檔案是沒有main主入口函數的,當測試一個方法的時候不能有傳回值,隻能是void

@Test注解是測試方法的意思,junit5常用注解的意思可以看它的​​官網說明​​

寫完了,然後運作一個test01即可,點一下test01左邊的綠色圓即可,如下圖所示:

hualinux spring 4.16:@Profile 切換環境

測試的結果如下:

testDataSource

jdbc:mysql://127.0.0.1:3306/hua_test?serverTimezone=GMT%2B8

devDataSource

jdbc:mysql://127.0.0.1:3306/hua_dev?serverTimezone=GMT%2B8

prodDataSource

jdbc:mysql://127.0.0.1:3306/hua?serverTimezone=GMT%2B8

hualinux spring 4.16:@Profile 切換環境

2.3 例2 在例1基礎加添加@Profile 注解

2.3.1 修改配置檔案

上面例1隻是測試是否讀到了配置,現在在配置檔案的各個bean中添加@Profile 注解指定一下配置名字名

com.hualinux.conf.MainConfProfile.java,修改部分代碼如下:

@Profile("test")
    @Bean("testDataSource")
    public DataSource dataSourceTest() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setDriverClass(driverClass);
        //測試環境使用的資料庫
        dataSource.setJdbcUrl(jdbcUrlTest);
        return dataSource;
    }

    @Profile("dev")
    @Bean("devDataSource")
    public DataSource dataSourceDev() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setDriverClass(driverClass);
        //開發環境使用的資料庫
        dataSource.setJdbcUrl(jdbcUrlDev);
        return dataSource;
    }

    @Profile("prod")
    @Bean("prodDataSource")
    public DataSource dataSourceProd() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(pwd);
        dataSource.setDriverClass(driverClass);
        //生産環境使用的資料庫
        dataSource.setJdbcUrl(jdbcUrlProd);
        return dataSource;
    }      
PS:上面3個@Profile注解中都沒有@Profile("default"),表示3個都不會激活,如果你運作test01結果為空的,什麼都沒有
hualinux spring 4.16:@Profile 切換環境

2.3.2 使用 @Profile("default")指定預設環境

如果我們要指定一個預設,比如本機開發,去這裡選擇dev環境,改成:

@Profile("default")
    @Bean("devDataSource")      

運作一下test01方法效果如下圖所示:隻能讀到一個預設的

hualinux spring 4.16:@Profile 切換環境

2.3.3 使用  -Dspring-prfofiles.active 激活指定環境

如果我有這麼下個需求,我不用預設配置,到使用的時候我再指定激活那個bean配置行不行,行!

那就得用到  -Dspring.profiles.active 參數激活指定環境,你把 2.3.2 的 @Profile("default")改回 @Profile("dev")

再按如下操作:

hualinux spring 4.16:@Profile 切換環境

的VM options:添加多一個   -Dspring.profiles.active=test

hualinux spring 4.16:@Profile 切換環境
注:這個配置一個要寫正确!  -Dspring.profiles.active=test 前面的小橫杠不能少,大小寫要一樣

再運作一個test01,看一下效果:

hualinux spring 4.16:@Profile 切換環境
hualinux spring 4.16:@Profile 切換環境

測試完之後再配置删除,恢複原來的

2.4 使用環境

我在上面的基礎上再添加多一個測試方法,看一下怎麼使用這個bean

test-->java-->IOCTest_Profile.java 添加多一個測試方法,如下:

@Test
    //注意test不能有傳回值隻能是void
    public void test02(){
        ctx=new AnnotationConfigApplicationContext();
        // 1. 建立一個 ApplicationContext,這裡沒有一開始就指定配置類
        ctx = new AnnotationConfigApplicationContext();
        //2. 設定需要激活的環境,在沒有指定預設的情況下
        ctx.getEnvironment().setActiveProfiles("dev");
        // 3. 注冊主配置類
        ctx.register(MainConfProfile.class);
        //4. 啟動重新整理容器
        ctx.refresh();

        String[] namesForType = ctx.getBeanNamesForType(DataSource.class);
        for (String name: namesForType){
            System.out.println(name);
            ComboPooledDataSource dataSource= (ComboPooledDataSource) ctx.getBean(name);
            System.out.println(dataSource.getJdbcUrl());
        }
        ctx.close();
    }