博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从读取properties文件说开去,浅谈web容器中类加载器
阅读量:6794 次
发布时间:2019-06-26

本文共 5164 字,大约阅读时间需要 17 分钟。

今天刚好有人让我写个通过读取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);
           
}
       
}
   
}
 
}

转载于:https://www.cnblogs.com/aquarius-bear/p/4126703.html

你可能感兴趣的文章
在服务器上运行Jar包
查看>>
C#遍历对象属性
查看>>
设置float之后vertical-align失效
查看>>
ABP官方文档翻译 2.3 缓存
查看>>
主动调用其他类的成员, 特殊成员
查看>>
JAVA数据结构-----栈
查看>>
【Boost】timer、progress_timer和progress_display
查看>>
mysql慢查询日志分析工具(python写的)
查看>>
ParentalControl-SteadyState
查看>>
Craniosynostosis Code Comments
查看>>
数据结构的学习
查看>>
习题5-7 使用函数求余弦函数的近似值
查看>>
设计模式--开篇
查看>>
字符、字符串和文本的处理之String类型
查看>>
使用T2表中的值替换T1表的值
查看>>
word怎样插入图片
查看>>
解决VMware Workstation虚拟机不能联网的解决办法
查看>>
win10配置的静态/动态IP和 DNS的方法
查看>>
HDU 4609 3-idiots
查看>>
会计的思考(22):美丽会计
查看>>