前阵子,准备重新测试一下tomcat对context.xml中数据源的处理情况,当时我的context.xml是这样写的,并且放在web目录下的META-INF目录下
1
2
3
4
5
6
7
|
<?
xml
version
=
'1.0'
encoding
=
'UTF-8'
?>
<
Context
>
<
resource
name
=
"jdbc/xx"
auth
=
"Container"
type
=
"javax.sql.DataSource"
password
=
"123456"
driverClassName
=
"com.mysql.jdbc.Driver"
username
=
"root"
url
=
"jdbc:mysql://127.0.0.1/xx"
/>
</
Context
>
|
并且相应的mysql.jar包已经放到tomcat的lib目录下,然后在进行运行之后,死活也找不到所配置的数据源信息。最后找了半天,错误原因也很 简单的,并不是context.xml位置不正确。在上面的xml配置中,resource节点中的resource应该写首字母大写,即应该为 Resource而不是resource。修改之后,一切正确了。
那么是什么原因导致tomcat找不到这里所写的小写的resource呢,这就涉及到tomcat内部对context.xml解析了。在tomcat 内部,是通过ContextConfig类来用于处理context.xml信息,并通过Digester类来完成对context.xml的解析,在具 体的解析过程中,正是因为对相应节点的匹配不成功,导致没有解析。但是不会发生错误。
在tomcat内部,使用ContextConfig来解析web.xml和context.xml,当仔细查看代码时,你会发现,解析web.xml和 context.xml使用的是同一个类,即org.apache.tomcat.util.digester.Digester,通过使用不同的 Rule对节点进行匹配,让匹配之后的Rule进行不同的操作,而Digester本身只做一个分发的作用,并不参与实际逻辑。整个流程可以由如下图所 示:
那么在整个Context.xml解析中加入了哪些RuleSet呢,可以由如何创建contextDigester的过程得出,如下代码所示:(以下代码在ContextConfig类中)
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
protected
Digester createContextDigester() {
Digester digester =
new
Digester();
digester.setValidating(
false
);
digester.setRulesValidation(
true
);
HashMap<Class<?>, List<String>> fakeAttributes =
new
HashMap<Class<?>, List<String>>();
ArrayList<String> attrs =
new
ArrayList<String>();
attrs.add(
"className"
);
fakeAttributes.put(Object.
class
, attrs);
digester.setFakeAttributes(fakeAttributes);
RuleSet contextRuleSet =
new
ContextRuleSet(
""
,
false
);
//用于解析在context.xml中常规的context选项
digester.addRuleSet(contextRuleSet);
RuleSet namingRuleSet =
new
NamingRuleSet(
"Context/"
);
//用于解析如本文中的命名服务信息
digester.addRuleSet(namingRuleSet);
return
digester;
}
|
ContextRuleSet和NamingRuleSet是一个规则集合,在详细的addRuleInstances(Digester digester)中,才把最终的规则加入到digester中。在tomcat中,每一条规则的描述即由一个规则名和具体规则实现来表示。规则名,即从 xml根节点名到子节点名的一个完整path,如context节点下的resource节点,就表示为Context/Resource。在 NamingRuleSet中,我们可以看到为Resource节点增加了3个规则,如下所示:
1
2
3
4
5
6
|
digester.addObjectCreate(prefix +
"Resource"
,
"org.apache.catalina.deploy.ContextResource"
);
digester.addRule(prefix +
"Resource"
,
new
SetAllPropertiesRule());
digester.addRule(prefix +
"Resource"
,
new
SetNextNamingRule(
"addResource"
,
"org.apache.catalina.deploy.ContextResource"
));
|
其中第一个规则,即创建一个ContextResource对象,即Resource的对象表示。第二个规则,就是将节点的相应属性进行设置,包括可以能 够识别的属性和通过setProperties设置的其他属性。第三个规则则是将这个对象添加到context下的namingresources集合 中。
通过对以上代码的了解,我们知道如果不是标准的xml节点,那么tomcat在解析中是不会解析的。因此,没有相应的解析规则可以匹配。那么,tomcat如何进一步解析本文中的resource节点,并加入到jndi中,则是下一篇文章则要分析的了。
转载请标明出处:i flym
本文地址:http://www.iflym.com/index.php/code/201208080002.html