从读取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);
			}
		}
	}

}
相关文章
相关标签/搜索