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

<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方法就能擷取到值。