zoukankan      html  css  js  c++  java
  • 从读取properties文件说开去,浅谈web容器中类加载器

    今天刚好有人让我写个通过读取properties连接数据库的小demo.

    汗啊,普通项目中可以使用的文件读取,在web项目中总报空指针异常.

    查阅了资料明白,赶紧记录下来,希望遇到此类问题的童鞋能引起重视。

    废话不说,直接进入主题!

    代码清单1:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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 {
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    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文件的工具类

    通过方法

    1
    loadPropertiesFile(String filePath)

    在普通java项目下可以正常读取properties文件,但是在web项目下,无法读取properties文件,报空指针异常。

    这里引出类的加载器的概念

    每个Class对象都保留着加载自己的类加载器的引用,可以通过Class对象的getClassLoader方法来获得其引用。ClassLoader通过loadClass方法来加载这个类。

    按照类加载器,首先应该加载父类,也就是通常所说的父类优先的原则,但是在web容器中加载顺序有所不同。

    通过查找资料找到这样的叙述:

    对于运行在 Java EE容器中的 Web 应用来说,类加载器的实现方式与一般的 Java 应用有所不同。不同的 Web 容器的实现方式也会有所不同。以 Apache Tomcat 来说,每个 Web 应用都有一个对应的类加载器实例。该类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的。这是 Java Servlet 规范中的推荐做法,其目的是使得 Web 应用自己的类的优先级高于 Web 容器提供的类。这种代理模式的一个例外是:Java 核心库的类是不在查找范围之内的。这也是为了保证 Java 核心库的类型安全。

    绝大多数情况下,Web 应用的开发人员不需要考虑与类加载器相关的细节。下面给出几条简单的原则:

    • 每个 Web 应用自己的 Java 类文件和使用的库的 jar 包,分别放在 WEB-INF/classesWEB-INF/lib目录下面。
    • 多个应用共享的 Java 类文件和 jar 包,分别放在 Web 容器指定的由所有 Web 应用共享的目录下面。
    • 当出现找不到类的错误时,检查当前类的类加载器和当前线程的上下文类加载器是否正确。

    于是对于一个普通web项目,properties文件可以放在src目录下,经过编译器编译之后目录变为WEB-INF/classes目录.

    路径变化后,只能通过类加载器来获得文件路径,否则无法加载。

    代码清单2:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    /**
    * 项目名称 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);
                }
            }
        }
     
    }
  • 相关阅读:
    HTTP状态代码
    安装mySQL数据库常见问题
    python3.6安装版本选择
    用连接池提高Servlet访问数据库的效率
    策略模式
    如何在vue项目中修改less变量,多主题项目解决方案
    【前端】vue项目 url中传递数组参数
    element date-picker默认值问题
    echart 折线图legend不显示的问题
    vue学习之父子组件通信两种方法
  • 原文地址:https://www.cnblogs.com/aquarius-bear/p/4126703.html
Copyright © 2011-2022 走看看