以下實踐的是Properties配置文件的基本操作方法。像spring使用xml做依賴注入時,這個配置文件起到非常實用的作用。
一、格式規范
參考wiki百科的格式簡介:https://zh.wikipedia.org/wiki/.properties,說明如下:
每個.properties 文件中的行通常存儲單個屬性。對於每一行可能有這么幾種格式,包括鍵=值,鍵 = 值,鍵:值,以及鍵 值。
.properties文件可以使用井號(#)或嘆號(!)作為一行中第一個非空白字符來表示它后面的所有文本都是一個注釋。反斜杠(\)用於轉義字符。
提供的示例如下:
# You are reading the ".properties" entry. ! The exclamation mark can also mark text as comments. # The key and element characters #, !, =, and : are written with # a preceding backslash to ensure that they are properly loaded. website = http\://en.wikipedia.org/ language = English # The backslash below tells the application to continue reading # the value onto the next line. message = Welcome to \ Wikipedia\! # Add spaces to the key key\ with\ spaces = This is the value that could be looked up with the key "key with spaces". # Unicode tab : \u0009\u4E2D\u6587
接下來在eclipse測試可行性。使用最簡單的代碼:
Properties prop = new Properties(); try { prop.load(Main.class.getResourceAsStream("test.properties")); for (Object key : prop.keySet()) { System.out.println(key + "=" + prop.get(key)); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
正常輸出,沒任何報錯,結果如下:
所以,參照wiki百科的寫法是完全兼容的。但是有一點需要注意的:為了避免讀取簡單易懂,最好不要換行;和中文會轉換成Unicode,當要寫中文時,建議用英文或者拼音代替。
提示:很多專業的寫法會分模塊寫,比如Test.ProjectName=Test;這樣也是完全兼容的。
二、存放位置及讀取
注意:非必要的時候不要使用絕對路徑,除非非常確定配置文件的位置。
讀取的重點在於路徑,路徑之后就是獲取文件流。參考此處進行文件路徑的獲取:http://www.cnblogs.com/EasonJim/p/6503612.html,實質上除了路徑獲取外其它方法有提供流的獲取。
application:
1、存放:在jar包中其實任何位置都可以放,因為最終都會按照開發工程的目錄結構復制到jar包中,只要獲取的方式對就可以了。比如放在src外面,src里面的特定包中,METE-INF文件夾內部等都可以。但是不要放在項目的根目錄,因為默認打jar包是不會復制進去的。
存放位置參考:
最終默認打application包時的目錄如下:
但是如果要把test3.properties文件打包進jar包時,可以手動Export導出jar包,包含進去:
最終得到如下jar包目錄:
但是非常不建議這么做,主要有如下幾點問題存在:
①如果使用File對象(http://www.cnblogs.com/EasonJim/p/6503612.html#autoid-0-1-0第二點)讀取文件時,指向的目錄是工作目錄;如果是eclipse運行時,指向的是eclipse的工作目錄;而用jar包運行時,指向的就是jar包所在的目錄;那么也就是說讀取的不是jar包內的文件,而是外部的文件;所以用File對象去讀取的方法在jar包上不可取。
②如果使用Class.class.getResource這類方法(http://www.cnblogs.com/EasonJim/p/6503612.html#autoid-0-2-0第三點)獲取的路徑,在eclipse上獲取是編譯后class目錄,而這個目錄默認只會復制src/appClientModule目錄下的文件,在項目根目錄下的文件是不會復制過去的,所以在eclipse上無法獲取到;但是通過后期打包加入test3.properties時,在jar包上本身和class同一級目錄,所以此時可以正常讀取。這樣一來也就是和調試時都不能同步,所以這里不建議放在根目錄。
2、讀取:參考:http://blog.csdn.net/u011063151/article/details/51888640
以下為用File對象和類方法獲取以上目錄結構文件的方法:
①File對象(不建議使用):
參考:http://www.cnblogs.com/EasonJim/p/6503612.html#autoid-0-1-0(第二中方法)
java.util.Properties類的load方法傳入的參數為InputStream,所以只要根據File對象構建出來即可,代碼如下:
new BufferedInputStream(new FileInputStream(new File("test3.properties"))); new BufferedInputStream(new FileInputStream(new File("appClientModule/test.properties"))); new BufferedInputStream(new FileInputStream(new File("appClientModule/META-INF/test2.properties"))); new BufferedInputStream(new FileInputStream(new File("appClientModule/properties/test/test1.properties")));
②類方法獲取(推薦使用):
類方法獲取有很多種,參考:http://www.cnblogs.com/EasonJim/p/6503612.html#autoid-0-2-0(第三種方法)
但是,用類方法獲取test3.properties文件就無法在elipse中獲取。所以下面代碼將省略,代碼如下:
Main.class.getResourceAsStream("/test.properties"); Main.class.getResourceAsStream("/properties/test/test1.properties"); Main.class.getResourceAsStream("/META-INF/test2.properties");
Main.class.getClassLoader().getResourceAsStream("test.properties"); Main.class.getClassLoader().getResourceAsStream("properties/test/test1.properties"); Main.class.getClassLoader().getResourceAsStream("META-INF/test2.properties");
Thread.currentThread().getContextClassLoader().getResourceAsStream("test.properties"); Thread.currentThread().getContextClassLoader().getResourceAsStream("properties/test/test1.properties"); Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/test2.properties");
ClassLoader.getSystemClassLoader().getResourceAsStream("test.properties"); ClassLoader.getSystemClassLoader().getResourceAsStream("properties/test/test1.properties"); ClassLoader.getSystemClassLoader().getResourceAsStream("META-INF/test2.properties");
注意:上面開頭的斜杠寫法,以及包的路徑寫法。
經過測試上面路徑在jar上正常運行:
下面開始測試各個類庫對properties文件的讀取:
注意:由於File對象的局限性,所以不作為測試。
① 使用java.util.Properties類的load(InputStream in)方法加載properties文件:
Properties prop2 = new Properties(); prop2.load(Main.class.getResourceAsStream("/test.properties")); System.out.println(prop2.getProperty("message")); prop2.load(Main.class.getResourceAsStream("/properties/test/test1.properties")); System.out.println(prop2.getProperty("message")); prop2.load(Main.class.getResourceAsStream("/META-INF/test2.properties")); System.out.println(prop2.getProperty("message")); System.out.println(""); Properties prop3 = new Properties(); prop3.load(Main.class.getClassLoader().getResourceAsStream("test.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Main.class.getClassLoader().getResourceAsStream("properties/test/test1.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Main.class.getClassLoader().getResourceAsStream("META-INF/test2.properties")); System.out.println(prop3.getProperty("message")); System.out.println(""); Properties prop4 = new Properties(); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("test.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("properties/test/test1.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/test2.properties")); System.out.println(prop4.getProperty("message")); System.out.println(""); Properties prop5 = new Properties(); prop5.load(ClassLoader.getSystemClassLoader().getResourceAsStream("test.properties")); System.out.println(prop5.getProperty("message")); prop5.load(ClassLoader.getSystemClassLoader().getResourceAsStream("properties/test/test1.properties")); System.out.println(prop5.getProperty("message")); prop5.load(ClassLoader.getSystemClassLoader().getResourceAsStream("META-INF/test2.properties")); System.out.println(prop5.getProperty("message"));
eclipse輸出結果:
jar輸出結果:
測試一切正常。
②使用java.util.ResourceBundle類的getBundle()方法:
注意:這個getBundle()方法的參數只能寫成包路徑+properties文件名,也就說不用帶文件的后綴。
System.out.println(ResourceBundle.getBundle("test").getString("message")); System.out.println(ResourceBundle.getBundle("properties/test/test1").getString("message")); System.out.println(ResourceBundle.getBundle("META-INF/test2").getString("message"));
eclipse輸出結果:
jar輸出結果:
測試一切正常。
③使用java.util.PropertyResourceBundle類的構造函數:
System.out.println(new PropertyResourceBundle(Main.class.getResourceAsStream("/test.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Main.class.getResourceAsStream("/properties/test/test1.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Main.class.getResourceAsStream("/META-INF/test2.properties")).getString("message")); System.out.println(""); System.out.println(new PropertyResourceBundle(Main.class.getClassLoader().getResourceAsStream("test.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Main.class.getClassLoader().getResourceAsStream("properties/test/test1.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Main.class.getClassLoader().getResourceAsStream("META-INF/test2.properties")).getString("message")); System.out.println(""); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("test.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("properties/test/test1.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/test2.properties")).getString("message")); System.out.println(""); System.out.println(new PropertyResourceBundle(ClassLoader.getSystemClassLoader().getResourceAsStream("test.properties")).getString("message")); System.out.println(new PropertyResourceBundle(ClassLoader.getSystemClassLoader().getResourceAsStream("properties/test/test1.properties")).getString("message")); System.out.println(new PropertyResourceBundle(ClassLoader.getSystemClassLoader().getResourceAsStream("META-INF/test2.properties")).getString("message"));
eclipse輸出結果:
jar輸出結果:
測試一切正常。
測試工程:https://github.com/easonjim/5_java_example/tree/master/propertiestest/application
Web:
1、存放:
基本都是任意位置,但是不能放在項目根目錄,如下圖所示參考:
對於最優的放置位置,參考:http://stackoverflow.com/questions/2161054/where-to-place-and-how-to-read-configuration-resource-files-in-servlet-based-app,說:如果propertiesfile是webapp特定的,最好是放置它/WEB-INF/classes
。如果您在IDE中開發標准WAR項目,請將其放在src
文件夾(項目的源文件夾)中。如果你使用Maven項目,將其放在/main/resources
文件夾中。
2、讀取:
①使用java.util.Properties類的load(InputStream in)方法加載properties文件:
Properties prop2 = new Properties(); prop2.load(Index.class.getResourceAsStream("/test4.properties")); System.out.println(prop2.getProperty("message")); prop2.load(Index.class.getResourceAsStream("/properties/test/test5.properties")); System.out.println(prop2.getProperty("message")); prop2.load(Index.class.getResourceAsStream("/webtest/test7.properties")); System.out.println(prop2.getProperty("message")); //以下為servlet獨有 prop2.load(request.getSession().getServletContext().getResourceAsStream("/META-INF/test3.properties")); System.out.println(prop2.getProperty("message")); prop2.load(request.getSession().getServletContext().getResourceAsStream("/WEB-INF/lib/test6.properties")); System.out.println(prop2.getProperty("message")); prop2.load(request.getSession().getServletContext().getResourceAsStream("/WEB-INF/test2.properties")); System.out.println(prop2.getProperty("message")); prop2.load(request.getSession().getServletContext().getResourceAsStream("/test1.properties")); System.out.println(prop2.getProperty("message")); System.out.println(""); Properties prop3 = new Properties(); prop3.load(Index.class.getClassLoader().getResourceAsStream("test4.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Index.class.getClassLoader().getResourceAsStream("properties/test/test5.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Index.class.getClassLoader().getResourceAsStream("webtest/test7.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Index.class.getClassLoader().getResourceAsStream("../../META-INF/test3.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Index.class.getClassLoader().getResourceAsStream("../lib/test6.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Index.class.getClassLoader().getResourceAsStream("../test2.properties")); System.out.println(prop3.getProperty("message")); prop3.load(Index.class.getClassLoader().getResourceAsStream("../../test1.properties")); System.out.println(prop3.getProperty("message")); System.out.println(""); Properties prop4 = new Properties(); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("test4.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("properties/test/test5.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("webtest/test7.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("../../META-INF/test3.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("../lib/test6.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("../test2.properties")); System.out.println(prop4.getProperty("message")); prop4.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("../../test1.properties")); System.out.println(prop4.getProperty("message")); System.out.println(""); //ClassLoader.getSystemClassLoader().getResourceAsStream()在web中不可用 /*Properties prop5 = new Properties(); prop5.load(ClassLoader.getSystemClassLoader().getResourceAsStream("test4.properties")); System.out.println(prop5.getProperty("message")); prop5.load(ClassLoader.getSystemClassLoader().getResourceAsStream("properties/test/test5.properties")); System.out.println(prop5.getProperty("message")); prop5.load(ClassLoader.getSystemClassLoader().getResourceAsStream("webtest/test7.properties")); System.out.println(prop5.getProperty("message"));*/
注意:上面的地址上巧妙的使用了【..】來返回上一級,並使用此方法替代了servlet特有的方法。
eclips中輸出:
war包輸出:
測試一切正常。
②使用java.util.ResourceBundle類的getBundle()方法:
注意:這個getBundle()方法的參數只能寫成包路徑+properties文件名,也就說不用帶文件的后綴。
System.out.println(ResourceBundle.getBundle("test4").getString("message")); System.out.println(ResourceBundle.getBundle("properties/test/test5").getString("message")); System.out.println(ResourceBundle.getBundle("webtest/test7").getString("message")); //以下無法正常獲取 /*System.out.println(ResourceBundle.getBundle("/../../META-INF/test3").getString("message")); System.out.println(ResourceBundle.getBundle("../lib/test6").getString("message")); System.out.println(ResourceBundle.getBundle("../test2").getString("message")); System.out.println(ResourceBundle.getBundle("../../test1").getString("message"));*/
eclips中輸出:
war包輸出:
測試一切正常。
③使用java.util.PropertyResourceBundle類的構造函數:
System.out.println(new PropertyResourceBundle(Index.class.getResourceAsStream("/test4.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getResourceAsStream("/properties/test/test5.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getResourceAsStream("/webtest/test7.properties")).getString("message")); //以下為servlet獨有 System.out.println(new PropertyResourceBundle(request.getSession().getServletContext().getResourceAsStream("/META-INF/test3.properties")).getString("message")); System.out.println(new PropertyResourceBundle(request.getSession().getServletContext().getResourceAsStream("/WEB-INF/lib/test6.properties")).getString("message")); System.out.println(new PropertyResourceBundle(request.getSession().getServletContext().getResourceAsStream("/WEB-INF/test2.properties")).getString("message")); System.out.println(new PropertyResourceBundle(request.getSession().getServletContext().getResourceAsStream("/test1.properties")).getString("message")); System.out.println(""); System.out.println(new PropertyResourceBundle(Index.class.getClassLoader().getResourceAsStream("test4.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getClassLoader().getResourceAsStream("properties/test/test5.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getClassLoader().getResourceAsStream("webtest/test7.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getClassLoader().getResourceAsStream("../../META-INF/test3.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getClassLoader().getResourceAsStream("../lib/test6.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getClassLoader().getResourceAsStream("../test2.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Index.class.getClassLoader().getResourceAsStream("../../test1.properties")).getString("message")); System.out.println(""); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("test4.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("properties/test/test5.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("webtest/test7.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("../../META-INF/test3.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("../lib/test6.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("../test2.properties")).getString("message")); System.out.println(new PropertyResourceBundle(Thread.currentThread().getContextClassLoader().getResourceAsStream("../../test1.properties")).getString("message"));
eclips中輸出:
war包輸出:
測試一切正常。
測試工程:https://github.com/easonjim/5_java_example/tree/master/propertiestest/web
三、操作:
對於操作,這里不做測試,一般原生方法中,只有Properties類的store方法。