今天恰好有人讓我寫個經過讀取properties鏈接數據庫的小demo. java
汗啊,普通項目中可使用的文件讀取,在web項目中總報空指針異常. web
查閱了資料明白,趕忙記錄下來,但願遇到此類問題的童鞋能引發重視。 數據庫
廢話不說,直接進入主題! apache
代碼清單1: 安全
import java.io.InputStream; import java.util.Properties; import org.apache.log4j.Logger; /** * * 項目名稱 PropertiesDemo * 包 名 com.linfeng.util * 文 件 名 PropertiesUtil.java * 開 發 人 Administrator * 描述信息 Properties文件讀取類 * 發佈日期 2012-10-31上午11:34:59 * 修改日期 * 修 改 人 * 版本信息 V1.0 * */ public class PropertiesUtil {
private static Logger log = Logger.getLogger(PropertiesUtil.class); private Properties propertie; private InputStream inputFile; public PropertiesUtil(String filePath){ propertie = new Properties(); try { inputFile = getClass().getResourceAsStream(filePath); propertie.load(inputFile); inputFile.close(); } catch (FileNotFoundException ex) { log.error("讀取屬性文件--->失敗!- 緣由:文件路徑錯誤或者文件不存在"); ex.printStackTrace(); } catch (IOException ex) { log.error("裝載文件--->失敗!"); ex.printStackTrace(); } } /** * 重載函數,獲得key的值 * @param key 取得其值的鍵 * @return key的值 */ public String getValue(String key) { if(propertie.containsKey(key)){ String value = propertie.getProperty(key);//獲得某一屬性的值 return value; } else return ""; }//end getValue(...) /** * 重載函數,獲得key的值 * @param fileName properties文件的路徑+文件名 * @param key 取得其值的鍵 * @return key的值 */ public String getValue(String fileName, String key) { try { String value = ""; inputFile = getClass().getResourceAsStream(fileName); propertie.load(inputFile); inputFile.close(); if(propertie.containsKey(key)){ value = propertie.getProperty(key); return value; }else return value; } catch (FileNotFoundException e) { e.printStackTrace(); return ""; } catch (IOException e) { e.printStackTrace(); return ""; } catch (Exception ex) { ex.printStackTrace(); return ""; } }//end getValue(...) /** * 根據指定資源路徑加載單個資源文件,返回Properties類對象的引用。 * 如有異常產生,則Properties類對象爲空。 * @param filePath 資源文件的路徑的值 * @return 給定資源文件所對應的Properties類對象的引用 */ public static Properties loadPropertiesFile(String filePath){ Properties properties= new Properties(); InputStream is = null; try { try{ is=new FileInputStream(filePath); properties.load(is); }finally{ if (is!=null) { is.close(); is=null; } } } catch (Exception e) { properties = null; } return properties; } }
PropertiesUtil.java 用於進行讀取*.properties文件的工具類 函數
經過方法 工具
loadPropertiesFile(String filePath)在普通java項目下能夠正常讀取properties文件,可是在web項目下,沒法讀取properties文件,報空指針異常。
這裏引出類的加載器的概念 url
每一個Class對象都保留着加載本身的類加載器的引用,能夠經過Class對象的getClassLoader方法來得到其引用。ClassLoader經過loadClass方法來加載這個類。 spa
按照類加載器,首先應該加載父類,也就是一般所說的父類優先的原則,可是在web容器中加載順序有所不一樣。 線程
經過查找資料找到這樣的敘述:
對於運行在 Java EE容器中的 Web 應用來講,類加載器的實現方式與通常的 Java 應用有所不一樣。不一樣的 Web 容器的實現方式也會有所不一樣。以 Apache Tomcat 來講,每一個 Web 應用都有一個對應的類加載器實例。該類加載器也使用代理模式,所不一樣的是它是首先嚐試去加載某個類,若是找不到再代理給父類加載器。這與通常類加載器的順序是相反的。這是 Java Servlet 規範中的推薦作法,其目的是使得 Web 應用本身的類的優先級高於 Web 容器提供的類。這種代理模式的一個例外是:Java 核心庫的類是不在查找範圍以內的。這也是爲了保證 Java 核心庫的類型安全。
絕大多數狀況下,Web 應用的開發人員不須要考慮與類加載器相關的細節。下面給出幾條簡單的原則:
WEB-INF/classes
和 WEB-INF/lib
目錄下面。
因而對於一個普通web項目,properties文件能夠放在src目錄下,通過編譯器編譯以後目錄變爲WEB-INF/classes目錄.
路徑變化後,只能經過類加載器來得到文件路徑,不然沒法加載。
代碼清單2:
/** * * 項目名稱 XXXX * 包 名 com.xxx.mall.util * 文 件 名 DbUtil.java * 開 發 人 Administrator * 描述信息 數據庫幫助類 * <p>數據庫鏈接方法</p> * <p>釋放數據庫資源方法</p> * 發佈日期 2012-10-31下午03:26:50 * 修改日期 * 修 改 人 * 版本信息 V1.0 * */ public class DbUtil { //Connection對象 private static Connection conn =null; private static final String PROPERTIES_FILE_PATH="/dbconfig.properties"; /** * 得到數據庫鏈接對象方法 * @return 返回數據庫鏈接對象conn */ public static Connection getConnection(){ try { PropertiesUtil propertiesUtil=new PropertiesUtil(PROPERTIES_FILE_PATH); Class.forName(propertiesUtil.getValue("driver")); conn=DriverManager.getConnection(propertiesUtil.getValue("url"), propertiesUtil.getValue("user"), propertiesUtil.getValue("password")); }catch (ClassNotFoundException e) { throw new MyDbException("數據庫jar包異常",e); }catch (SQLException e) { throw new MyDbException("數據庫鏈接字符串異常",e); } catch (Exception e) { throw new MyDbException("數據庫鏈接異常",e); } return conn; } /** * 釋放數據庫資源方法 * @param pmst * @param rs * @param conn */ public static void freeDb(PreparedStatement pmst,ResultSet rs,Connection conn){ if (pmst!=null) { try { pmst.close(); } catch (SQLException e) { throw new MyDbException("數據庫關閉PreparedStatement對象異常",e); } } if (rs!=null) { try { rs.close(); } catch (SQLException e) { throw new MyDbException("數據庫關閉ResultSet對象異常",e); } } if (conn!=null) { try { conn.close(); } catch (SQLException e) { throw new MyDbException("數據庫關閉Connection對象異常",e); } } } }