目前大多數的架構設計中都會採用外部化配置,由於從開發、測試、預發再到生產,不一樣的環境有不一樣的配置,不可能每次爲了改配置而去改代碼。因此外部化配置已是一個不可或缺的設計。目前配置存儲的文件類型也有yaml、properties等。今天我就來說講Java讀取properties文件的數據的n種方法。java
讀取*.properties文件主要分兩步:spring
根據找資源路徑的不一樣方法以及加載資源數據的不一樣方法,將方法主要分爲了如下8種:markdown
1、基於ClassLoder的getResourceAsStream方法讀取配置文件架構
2、基於getResourceAsStream()方法讀取配置文件app
3、基於ClassLoader類的getSystemResourceAsStream()靜態方法讀取配置文件測試
4、基於 FileInputStream 讀取配置文件this
5、基於ResourceBundle讀取配置文件url
6、基於PropertyResourceBundle讀取配置文件spa
7、基於xml方式讀取配置架構設計
8、基於註解讀取配置
下面我進行一一講解,首先我在resources下建立了一個config.properties,其中只包含一條配置就是name=crazyhzm。如下示例都是模擬讀取該文件中的name屬性。
本方法基於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")); } } 複製代碼
這種方法是利用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()靜態方法來定位資源,而且返回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")); } } 複製代碼
這種方法經過類的路徑來定位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實際上是用來解決國際化和本地化問題的,可是須要在多種語言中切換,必然會有一個配置文件來指定切換的內容,好比須要把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是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")); } } } 複製代碼
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.10.RELEASE</version> </dependency> 複製代碼
@Service public class UserService { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 複製代碼
<?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> 複製代碼
<?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> 複製代碼
public class UserService { @Value("${name}") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } 複製代碼