天天看點

Spring Boot擷取配置檔案内容方法總結

一、前言

一種場景下是為了降低代碼的耦合,需要将一些配置參數放到配置檔案中(資料庫中也是一個方式),以免以後修改時去代碼中一個一個找;另一種場景就是一個項目會有開發環境,測試環境、生産環境等等,每個環境下,(比如連接配接的資料庫的位址不同)或者其他的一些自定義屬性不同。

二、擷取自己建立的xxx.properties檔案中的屬性值

<1> task.properties (在resource根目錄下的)

queryNumber=200
taskOneCode=bsa
taskTwoCode=bs
taskThreeCode=ba
           

<2> PropertiesUtil.java

package com.zlc.springcloud.util;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

@Component
public class PropertiesUtil {
    private static final Logger log = LoggerFactory.getLogger(PropertiesUtil.class);
  
    /**描述: 擷取properties配置檔案的value
     *@param key 鍵值
     *@return  :  env.getProperty(key) value值      
     *@Author :  追到烏雲的盡頭找太陽
     *建立時間:2017/9/6
     */
    public String getPropertiesValue( String propertiesName , String key){
        Configuration propertiesConfig ;
        //  擷取classpath 路徑下的properties檔案,如果檔案不在跟目錄,請在propertiesName 前加上檔案名稱,可以在此基礎上改造
        String properties = propertiesName+".properties";
        String value ;  
        //傳回properties中的參數
        try {
            propertiesConfig = new PropertiesConfiguration(properties);
            value = propertiesConfig.getString(key);
            if (null== propertiesConfig.getString(key)  || "".equals(propertiesConfig.getString(key))) {
                log.error( "擷取 {} 配置檔案中key為 {} 的值不存在" ,properties, key );
            }else {
                return value;
            }
        } catch (ConfigurationException e) {
            log.error("讀取配置檔案異常,異常資訊為:"+ e);
            e.printStackTrace();
            value = null;
        } 
        return value;
    }

    /**
     * 修改properties檔案中屬性值對應的值,打成jar包無法修改
     * @param propertiesName properties檔案名稱
     * @param key 屬性名稱
     * @param value 屬性值
     */
    public void updateProperties(String propertiesName, String key, String value){

        String basePath = this.getClass().getResource("/").getPath() + propertiesName;
        FileReader fr = null;
        BufferedReader bf = null;
        StringBuilder buf = new StringBuilder();
        try {
            fr = new FileReader(basePath);
            bf = new BufferedReader(fr);

            String line = null;
            while( (line = bf.readLine()) != null){
                String cloneLine = line;
                if(line.trim().indexOf("#", 0) == 0){
                    buf.append(cloneLine);
                }else{
                    String property = cloneLine.trim().split("=")[0];
                    if(key.equals(property.trim())){
                        buf.append(property.trim() + " = " + value);
                    }else{
                        buf.append(cloneLine);
                    }
                }
                buf.append(System.getProperty("line.separator"));
            }
        } catch (IOException e) {
            //檔案讀取失敗
            e.printStackTrace();
        } finally{
            if(bf != null){
                try {
                    bf.close();
                } catch (IOException e) {
                    //帶緩沖的字元輸入流關閉失敗
                    e.printStackTrace();
                }
            }
        }

        FileWriter fw = null;
        BufferedWriter bw = null;
        try {
            fw = new FileWriter(basePath);
            bw = new BufferedWriter(fw);
            bw.write(buf.toString());
        } catch (IOException e) {
            //字元輸出流類建立失敗
            e.printStackTrace();
        } finally {
            if(bw != null){
                try {
                    bw.close();
                } catch (IOException e) {
                    //帶緩沖的字元輸出流關閉失敗
                    e.printStackTrace();
                }
            }
        }
    }
}

           

<3> 測試例子就不貼了,可以根據自己的想法對上述方法改造。需要注意的是修改方法,打成jar包後是無法修改的(因為打成jar包後,這個檔案的路徑變了,我已經測試過了,可以不要在踩這個坑了)

三、不同環境擷取同一key對應的不同值

就像上面說的,開發、測試、生産環境不同,這個時候同一個屬性在不同環境下就可能配置不同的value,擷取application.properties 中的屬性值很友善。舉例:一種情況下,一個webservice請求位址(最近在研究這個,是以舉這個例子)在生産環境、測試環境和生産環境是不同的,這個時候就需要在不同的配置檔案中寫好,因為springBoot的jar包運作時可以通過指定激活檔案的方式運作(當然也可以通過指定配置檔案裡面的值);還有一點就是properties檔案和yaml檔案是一樣的(yml檔案在運作的時候最後也會變成properties,下面介紹的這種方式也是通過springBoot中的PropertiesFactory弄得)

java -jar x.jar --spring.profiles.active=test
           

上面就是激活test環境

Spring Boot擷取配置檔案内容方法總結

<1> application.yml

server:
  port: 9400
spring:
  profiles:
    active: dev
           

<2> application-dev.yml (開發環境)

#自定義配置,上面可以配置其他
myconfig:
  webservice-url: http://10.126.16.57:7001/services/CallService?wsdl
  batchconfig:
    query-number: 200
    # 機關毫秒
    sleep-time: 500
    connection-timeout: 60000
    receive-timeout: 120000
           

<3> application-test.yml ( 測試環境)

#自定義配置,上面可以配置其他
myconfig:
  webservice-url: http://10.126.16.27:7001/services/CallService?wsdl
  batchconfig:
    query-number: 500
    # 機關毫秒
    sleep-time: 1000
    connection-timeout: 30000
    receive-timeout: 120000
           

<4> 修改後的PropertiesUtil.java

package com.zlc.springcloud.util;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.io.*;

@Component
public class PropertiesUtil {
    private static final Logger log = LoggerFactory.getLogger(PropertiesUtil.class);
    
    private final Environment env;

    public PropertiesUtil(Environment env) {
        this.env = env;
    }

    /**描述: 擷取激活配置檔案的value
     *@param key 鍵值
     *@return  :  env.getProperty(key) value值      
     *@Author :追到烏雲的盡頭找太陽
     *建立時間:2019/9/6
     */
    public String getPropertiesValue(String key) throws Exception {
        if (env.containsProperty(key)){
            return env.getProperty(key);
        }else {
        // 沒找到對應的值,調用該方法的地方需要捕獲異常,否則傳回(null),根據自己的情況弄
            throw new Exception();
        }
    }
    
    public String getPropertiesValue( String propertiesName , String key){
        Configuration propertiesConfig ;
        String properties = propertiesName+".properties";
        String value ;  
        //傳回properties中的參數
        try {
            propertiesConfig = new PropertiesConfiguration(properties);
            value = propertiesConfig.getString(key);
            if (null== propertiesConfig.getString(key)  || "".equals(propertiesConfig.getString(key))) {
                log.error( "擷取 {} 配置檔案中key為 {} 的值不存在" ,properties, key );
            }else {
                return value;
            }
        } catch (ConfigurationException e) {
            log.error("讀取配置檔案異常,異常資訊為:"+ e);
            e.printStackTrace();
            value = null;
        } 
        return value;
    }  
}

           

如果你激活了dev ,那麼你調用這個方法擷取webservice的位址就是在dev環境下的;為什麼沒用@Value注解呢?因為@Value 一直都是擷取application.yml檔案下的,也就是一直傳回null,是以沒用,況且不能判斷是否含有這個key,就使用了上面的方法。

@Value("${myconfig.webservice-urll}")
private String url;
           

這種方式擷取application.yml檔案下是能成功的,但是無法根據不同的環境擷取不同的值,也沒什研究。

補充:通過 @Configuration

@ConfigurationProperties(prefix = “config”)

直接添加到類上,prefix = "batch-config"是擷取application-xxx檔案的中配置參數字首的,這個方法簡單。@ConfigurationProperties(prefix = “config”)注解也可以放到方法上。

package com.springcloud.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author : 追到烏雲的盡頭找太陽
 **/
@Configuration
@ConfigurationProperties(prefix = "batch-config")
public class BatchConfig {
    private String queryNumber;
    private String sleepTime;

    public String getQueryNumber() {
        return queryNumber;
    }

    public void setQueryNumber(String queryNumber) {
        this.queryNumber = queryNumber;
    }

    public String getSleepTime() {
        return sleepTime;
    }

    public void setSleepTime(String sleepTime) {
        this.sleepTime = sleepTime;
    }
}

           

application-dev中如下:

batch-config:
  query-number: 200
  # 機關毫秒
  sleep-time: 500
           

使用的時候隻需要通過get方法就能擷取到值。

繼續閱讀