![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CN1UjNiNTO1QzNlNGMxITOwgTYykTY2kjZyYGO4MTZy8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
前言
目前大多數的架構設計中都會采用外部化配置,因為從開發、測試、預發再到生産,不同的環境有不同的配置,不可能每次為了改配置而去改代碼。是以外部化配置已經是一個不可或缺的設計。目前配置存儲的檔案類型也有yaml、properties等。今天我就來講講Java讀取properties檔案的資料的n種方法。
讀取*.properties檔案主要分兩步:
- 找到資源路徑
- 加載資源
根據找資源路徑的不同方法以及加載資源資料的不同方法,将方法主要分為了以下8種:
一、基于ClassLoder的getResourceAsStream方法讀取配置檔案
二、基于getResourceAsStream()方法讀取配置檔案
三、基于ClassLoader類的getSystemResourceAsStream()靜态方法讀取配置檔案
四、基于 FileInputStream 讀取配置檔案
五、基于ResourceBundle讀取配置檔案
六、基于PropertyResourceBundle讀取配置檔案
七、基于xml方式讀取配置
八、基于注解讀取配置
下面我進行一一講解,首先我在resources下建立了一個config.properties,其中隻包含一條配置就是name=crazyhzm。以下示例都是模拟讀取該檔案中的name屬性。
一、基于ClassLoder的getResourceAsStream方法讀取配置檔案
本方法基于ClassLoder的getResourceAsStream方法,通過類加載器來定位資源,傳回InputStream後用Properties對象進行加載。
public class Test {
public static void main(String[] args) throws IOException {
InputStream in = Test.class.getClassLoader().getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(in);
System.out.println(properties.getProperty("name"));
}
}
二、基于getResourceAsStream()方法讀取配置檔案
這種方法是利用class的getResourceAsStream方法來定位資源檔案,并且直接傳回InputStream對象,然後通過Properties進行加載。
public class Test {
public static void main(String[] args) throws IOException {
InputStream in = Test.class.getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(in);
System.out.println(properties.getProperty("name"));
}
}
三、基于ClassLoader類的getSystemResourceAsStream()靜态方法讀取配置檔案
該方法使用ClassLoader的getSystemResourceAsStream()靜态方法來定位資源,并且傳回InputStream,最後用Properties來加載。其實上一種方法的getResourceAsStream中也調用了ClassLoader.getSystemResourceAsStream,我們來看看源碼:
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
該方法示例:
public class Test {
public static void main(String[] args) throws IOException {
InputStream in = ClassLoader.getSystemResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(in);
System.out.println(properties.getProperty("name"));
}
}
四、基于 FileInputStream 讀取配置檔案
這種方法通過類的路徑來定位properties檔案資源的路徑,然後通過FileInputStream讀取流,最後通過java.util.Properties類的load()方法來加載資料。
public class Test {
public static void main(String[] args) throws IOException {
URL url = Test.class.getClassLoader().getResource("config.properties");
if (url != null) {
String fileName = url.getFile();
InputStream in = new BufferedInputStream(new FileInputStream(fileName));
Properties properties = new Properties();
properties.load(in);
System.out.println(properties.getProperty("name"));
}
}
}
五、基于ResourceBundle讀取配置檔案
ResourceBundle其實是用來解決國際化和本地化問題的,但是需要在多種語言中切換,必然會有一個配置檔案來指定切換的内容,比如需要把click轉化為點選。那需要在配置檔案中将這兩個值進行對應,具體的我就不再這裡贅述,跟本文關系不大,在讀取配置檔案時候,利用ResourceBundle來讀取properties檔案也不乏是一種方案。
下面為了使用ResourceBundle,我新增了一個配置檔案,名叫config_en_US.properties,内容和config.properties一樣,你會發現建立完後,Resource檔案夾名字有點變化了。。
下面是使用示例:
public class Test {
public static void main(String[] args) throws IOException {
Locale locale1 = new Locale("en", "US");
ResourceBundle resourceBundle = ResourceBundle.getBundle("config", locale1);
System.out.println(resourceBundle.getString("name"));
}
}
六、基于PropertyResourceBundle讀取配置檔案
PropertyResourceBundle是ResourceBundle的子類,同樣我們也可以利用PropertyResourceBundle來加載配置檔案的資料,具體的示例如下:
public class Test {
public static void main(String[] args) throws IOException {
URL url = Test.class.getClassLoader().getResource("config.properties");
if (url != null) {
InputStream in = new BufferedInputStream(new FileInputStream(url.getFile()));
ResourceBundle resourceBundle = new PropertyResourceBundle(in);
System.out.println(resourceBundle.getString("name"));
}
}
}
七、基于xml方式讀取配置
- 加入依賴spring-context:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
- 建立UserService
@Service
public class UserService {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 建立application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:config.properties"/>
<bean id="userService" class="UserService">
<property name="name" value="${name}"/>
</bean>
</beans>
- 編寫測試類
@Service
public class Test {
@Resource
private UserService userService;
@PostConstruct
public void getName(){
System.out.println(userService.getName());
}
}
這種方式必須通過Spring來加載bean,才能夠注入屬性值,這邊寫的@PostConstruct隻是為了用來測試,啟動前需要搭建一個啟動類。這種方式需要注意的是被注入的屬性必須實作setter方法,比如setName。
八、基于注解讀取配置
還是上述方法的例子,這次的xml隻需要加載properties,而自動注入則由@Value注解來完成。
- 引入依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
- 編寫application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:config.properties"/>
</beans>
- 編寫UserService
public class UserService {
@Value("${name}")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}