最近在重構自己的小Demo 想把自己的下Demo 變成可以配置的程序。但是遇到了一些困難,走了不少的彎路,最終還是解決了。

如果你是個牛人,你不用看了,寫這些東西是給和我一樣的菜鳥看的。
先說說我的Demo吧,我寫的是一個簡單新聞管理系統,很簡陋的那種,不過麻雀雖小,但是五臟俱全。
基本的增、刪、查、改,都有,用到了FCKeditor。一開始我連接數據庫用的是最原始的方法,把數據庫的連接信息全寫在代碼里,寫完以后就沒去管他了,十一放假這幾天,看了看自己的代碼,覺得代碼結果不好,于是就開始重構自己的代碼,首先就是重寫數據庫的連接管理我把連接數據庫的一些基本信息寫到了database.properties 文件里,然后從程序中讀取連接數據庫所需要的信息。但是看似簡單的東西,比且很容易的完成的工作,我卻遇到了不少麻煩。首先就是路徑的問題,其次是該以何種方式讀取;就這兩個問題困擾了兩天。(呵呵,見笑了

)
java讀取propterties文件有三種方法:
ClassLoader.getResourceAsStream ("some/pkg/resource.properties");
Class.getResourceAsStream ("/some/pkg/resource.properties");
ResourceBundle.getBundle ("some.pkg.resource");
注意括號中代碼的不同。
先讓大家看一段代碼吧:
DataSource.java 文件:
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*一個單子設計模式數據庫連接
* @author guanminglin
*/
public class DataSource {
public static Connection conn;
public DataSource() throws IOException {
{
try {
Properties props = new Properties();
//一定要用DataSource
InputStream in = DataSource.class.getResourceAsStream("/org/news/comm/database.properties");
//原先試過這下面兩種方法,但是都不行
//FileInputStream in = new FileInputStream("database.properties");
//InputStream in = Object.class.getResourceAsStream("/org/news/comm/database.properties")
//下面兩行是用來測試的
String s = in.toString();
System.out.println("s=="+s);
props.load(in);
in.close();
String drivers = props.getProperty("jdbc.drivers");
String url = props.getProperty("jdbc.url");
String username = props.getProperty("jdbc.username");
String password = props.getProperty("jdbc.password");
Class.forName(drivers);
conn = DriverManager.getConnection(url, username, password);
in.close();
} catch (SQLException ex) {
Logger.getLogger(DataSource.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(DataSource.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
*如果連接為空則建立一個新連接
* @return
*/
public static Connection getConnection() throws IOException {
if (conn == null) {
new DataSource();
}
return conn;
}
public void test(){
String str = new String();
}
public static void main(String[] args) throws IOException {
// TODO code application logic here
//用于測試
new DataSource();
System.out.print(conn);
}
}
我的文件包結構:
第一個要說的是:
FileInputStream in = new FileInputStream("database.properties");
網上有很多人說這條語句是從當前目錄中加載database.properties文件的,但是我得出的結果是:它是從classpath 中加載database.properties文件的。
因為我用的是IDE 是NetBeans 我以為直接放在當前包內就可以了,但是我發現這樣不行。具體放哪里我也不知道,后來用了另一種方法:
InputStream in = Object.class.getResourceAsStream("/org/news/comm/database.properties")
基本上是可以用了,一開始測試的時候還挺開心的。很順利的就通過了,但是當我真正運行項目的時候問題又來了,程序報了 空指針引用 錯誤。我就很納悶了為什么在單個文件里測試可以很容易的通過,一運行項目就會報錯呢?于是開始Debug,不Debug 不知道,一用嚇一跳:
InputStream in = Object.class.getResourceAsStream("/org/news/comm/database.properties")
in的值竟然是空的,難怪會報空指針錯誤了。單獨測試DataSource.java文件的時候運行正常啊,沒有報錯,in 也有值,但是為什么運行項目的時候又沒有值了呢?很是不解。
于是我google 了一把,最后看現了幾篇好文章 說的是如何讀取 propterties 文件。最終我發現用第二種
方法是有弊端的,關鍵就在Object 上,它所有類的父類,在單個文件中用他來讀取propterties文件還可以但是一運行項目,他就不起作用了,也不知道為什么。難道是java 的bug??或者說是NetBeans的bug??
我同樣的Eclipse 下測試過,結果是一樣的。
最后我將輸入流語句稍微改了一下,變成下面的樣子:
InputStream in = DataSource.class.getResourceAsStream("/org/news/comm/database.properties")
其實就是改個類名而已,讓他自身去定位propterties文件,就解決問題了。(
注意括號中紅色的部分,org前面的 "/" 絕對不能少,要不然會報錯的。)
無論是測試單文件還是,測試整個項目都沒問題了。(那個高興啊

)
database.propterties 文件很簡單:
jdbc.drivers = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/news
jdbc.username = root
jdbc.password = root
總結一下讀取propterties文件方法的不同:(JavaWorld里的內容,呵呵拿來用一下)
Behavioral differences
Method |
Parameter format |
Lookup failure behavior |
Usage example |
ClassLoader.
getResourceAsStream() |
"/"-separated names; no leading "/" (all names are absolute) |
Silent (returns null )
|
this.getClass().getClassLoader()
.getResourceAsStream
("some/pkg/resource.properties") |
Class.
getResourceAsStream() |
"/"-separated names; leading "/" indicates absolute names; all other names are relative to the class's package |
Silent (returns null )
|
this.getClass()
.getResourceAsStream
("resource.properties") |
ResourceBundle.
getBundle() |
"."-separated names; all names are absolute; .properties suffix is implied
|
Throws unchecked
java.util.MissingResourceException |
ResourceBundle.getBundle
("some.pkg.resource") |
|
推薦給大家一篇JavaWorld里面好的文章,里面講述使用不同方式讀出propterties文件的方式,以及他們之間的不同:
Smartly load your properties