1. 程式人生 > >【SpringBoot探索三】新增配置檔案

【SpringBoot探索三】新增配置檔案

使用配置檔案初探

(一).最簡單的配置

檔案型別支援兩種,yml和properties,springboot使用配置檔案很簡單,只需在resources目錄下建立application.properties檔案,編碼最好選擇utf-8,統一編碼格式,
建立一個測試配置項

test.value=test

使用@vaule註解在程式中引用test.value的值

@Value("${test.value}")
private String testValue;

這樣專案執行後,”test”就自動注入給了testValue

(二).使用Bean來管理多個配置項

如果我們的配置項有多個,springboot官方推薦使用java bean來進行管理。

再增加一個配置項

test.value1=test1
@Value("${test.value1}")
private String testValue1;

建立一個java bean 裡面做配置項的注入
ConfigBean.java

package com.my.webapp.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 配置檔案中的Bean管理
 */
@Component @ConfigurationProperties(prefix = "test") public class ConfigBean { private String value; private String value1; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getValue1() { return
value1; } public void setValue1(String value1) { this.value1 = value1; } }

使用@ConfigurationProperties註解,同時可以加上字首”test”,這樣test.value,test.value1分別注入給了value和value1
在程式碼中使用

 @Autowired
private ConfigBean configBean;
logger.info("test.value: "+configBean.getValue());

(三).建立多環境配置檔案

在實際企業開發中我們的環境有多種,不可能僅僅application.properies就能滿足使用,比如開發,測試,生產。不同環境下需要切換不同的配置檔案,因此可以配合maven進行配置檔案的切換
建立三套配置檔案,並分別在三個檔案設定test.value和test.value1不同的值
application-test.properties

test.value=test
test.value1=test1

application-dev.properties

test.value=dev
test.value1=dev1

application-prod.properties

test.value=prod
test.value1=prod1

再通過maven選配指定配置引數
web專案module對應pom檔案下進行修改
pom.xml

 <!--maven定義生效的配置
        三種環境 test dev prod
        啟用方式 1.<activeByDefault> 
                2.mvn命令 -P test|dev|prod
    -->
    <profiles>
        <profile>
            <id>test</id>
            <properties>
                <profileActive>test</profileActive>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
    </profiles>
    <build>
        <finalName>webapp-controller</finalName>
        <!--設定資原始檔-->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <!--排除的資原始檔-->
                <excludes>
                    <exclude>application.properties</exclude>
                    <exclude>application-*.properties</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <!--包含的資原始檔-->
                <includes>
                    <include>application.properties</include>
                    <include>application-${profileActive}.properties</include>
                </includes>
            </resource>
        </resources>

設定屬性配置三種環境 profile的選擇可以在執行maven命令時進行指定,當我們編譯打包時

Mvn -f clean package -P dev -Dmaven.test.skip=true;

-P引數即可指定,當前選擇的是dev。則id為dev的配置生效

如果我們不指定則預設使用指定了為true的配置。

最後我們還需要在application.properties檔案中配置一項

spring.profiles.active=@profileActive@

該檔案可以獲取到maven中配置的的屬性值,使用方式為@屬性名@,springboot根據application-@[email protected]載入具體的配置檔案,maven中預設是test 則預設載入application-test.properties檔案了。

(四).對配置檔案中的指定配置項進行加密

由於配置檔案中的配置項包含很多敏感資料,比如資料庫使用者密碼。如果我們需要對該屬性進行加密,並且程式能夠正常解析。

這裡需要用到國外大牛寫的一個java實現的安全框架:jaspyt

在pom檔案中加入該依賴

<dependency>
        <groupId>com.github.ulisesbocchio</groupId>
        <artifactId>jasypt-spring-boot-starter</artifactId>
        <version>1.14</version>
</dependency>

這樣我們程式就具有了對配置檔案進行加密解密的功能了,具體怎麼使用請參考以上別人的連結該框架預設使用的加密演算法為PBEWithMD5AndDES,我們可以自定義加密演算法進行加密解密

這裡使用了DES加密演算法

DESUtil.java

package com.cdvcredit.common.utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.SecureRandom;
import java.util.Base64;


public class DESUtil {

    public static String encrypt(String plainText, String privateKey) {

        try {
            KeyGenerator keygen = KeyGenerator.getInstance("DES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(privateKey.getBytes());

            keygen.init(56, secureRandom);
            SecretKey secretKey = keygen.generateKey();

            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] cipherBytes = cipher.doFinal(plainText.getBytes("utf-8"));
            byte[] plainTextBytes = Base64.getEncoder().encode(cipherBytes);

            return new String(plainTextBytes, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public static String decrypt(String cipherText, String privateKey) {
        try {
            KeyGenerator keygen = KeyGenerator.getInstance("DES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(privateKey.getBytes());

            keygen.init(56, secureRandom);
            SecretKey secretKey = keygen.generateKey();

            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);

            byte[] cipherTextBytes = Base64.getDecoder().decode(cipherText.getBytes("utf-8"));
            byte[] cipherBytes = cipher.doFinal(cipherTextBytes);

            return new String(cipherBytes, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

接下來則是用自定義加密演算法替換預設加密解密演算法
jaspyt預設通過StringEncryptor進行加密解密,我們只需要覆蓋該實現即可
編寫一個實現StringEncryptor介面的類,覆寫encrypt()和decrypt()方法

PropertiesEncryptor.java

package com.cdvcredit.api.app.component;

import com.cdvcredit.common.utils.DESUtil;
import com.cdvcredit.common.utils.FileUtil;
import org.jasypt.encryption.StringEncryptor;

import java.net.URL;

public class PropertiesEncryptor implements StringEncryptor {

    private String privateKey;

    private static String privateKeyFileName = "properties_key.txt";

    public PropertiesEncryptor() {
        super();
        this.privateKey = getPrivateKeyString();

    }

    @Override
    public String encrypt(String s) {
        return DESUtil.encrypt(s, privateKey);
    }

    @Override
    public String decrypt(String s) {
        return DESUtil.decrypt(s, privateKey);
    }

    private String getPrivateKeyString() {
        ClassLoader classLoader = getClass().getClassLoader();
        URL url = classLoader.getResource(privateKeyFileName);
        if (url == null) {
            return null;
        }
        System.out.println(url.getFile());
        return FileUtil.readToString(url.getFile());
    }
}

在這裡加解密所需要的金鑰暫時是存放在一個本地檔案”properties_key.txt”中,getPrivateKeyString()方法是從該檔案中取出該金鑰

FileUtil.java

package com.cdvcredit.common.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class FileUtil {

    public static String readToString(String pathName) {
        File file = new File(pathName);
        StringBuilder result = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String s = null;
            while ((s = br.readLine()) != null) {
                result.append(s);
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return result.toString();
    }

}

最後通過java config讓spring啟動載入我們覆蓋後的加解密類PropertiesEncryptor

PropertiesEncryptorConfig.java

package com.cdvcredit.api.app.component;

import org.jasypt.encryption.StringEncryptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class PropertiesEncryptorConfig {
    @Bean(name = "jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() {
        return new PropertiesEncryptor();

    }
}

這裡需要注意jaspyt根據bean名”jasyptStringEncryptor”去查詢加解密工具

對明文如何進行加密?

我們可以編寫一個測試方法

@Autowired
    private StringEncryptor jasyptStringEncryptor;
    @Test
    public void encryptTest(){
        System.out.println(jasyptStringEncryptor.encrypt("dev"));
    }

執行後得到KbYBe+WcTEM=

我們在配置檔案中加上該屬性值,格式為ENC(‘密文’),這樣的格式才會被jaspyt框架識別並解密

application-dev.properties

test.value=ENC(KbYBe+WcTEM=)
test.value1=dev1