從讀取properties文件說開去,淺談web容器中類加載器

今天恰好有人讓我寫個經過讀取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 應用本身的 Java 類文件和使用的庫的 jar 包,分別放在 WEB-INF/classes和 WEB-INF/lib目錄下面。
  • 多個應用共享的 Java 類文件和 jar 包,分別放在 Web 容器指定的由全部 Web 應用共享的目錄下面。
  • 當出現找不到類的錯誤時,檢查當前類的類加載器和當前線程的上下文類加載器是否正確。




因而對於一個普通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);
			}
		}
	}

}
相關文章
相關標籤/搜索