Tomcat源码阅读四:Digester工具
来源:互联网 发布:异地备份软件 编辑:程序博客网 时间:2024/06/05 05:06
为了不将一些tomcat配置写在代码里, tomcat使用了配置文件server.xml来记录系统配置。同时,使用开源库Digester将xml文件中的元素转换为java对象。
<office>
<address streeName="Wellington Street" streetNumber="100"/>
</office>
</employee>
有,调用该rule的begin方法;
(2)然后,它会遇到office的开始标签,检查是否有rule与模式employee/office相关联,若有,调用
该rule的begin方法;
(3)接下来遇到address的开始标签,执行过程与前面相同;
(4)然后,遇到前面已经遇到的标签的结束标签,调用各自rule的end方法。
addRule(pattern,
new ObjectCreateRule(className));
}
配置文件中的标签 称为模式,如<?xml version="1.0" encoding="ISO-8859-1"?>
<employee firstName="Brian" lastName="May"><office>
<address streeName="Wellington Street" streetNumber="100"/>
</office>
</employee>
DIigester解析xml时使用一种规则来约定如何解析,规则类是是Rule类的子类。以下是在解析xml文件时,digester做的一些事:
(1)digester会先遇到employee的开始标签,因此,它会检查是否有rule和模式employee相关联。 若有,调用该rule的begin方法;
(2)然后,它会遇到office的开始标签,检查是否有rule与模式employee/office相关联,若有,调用
该rule的begin方法;
(3)接下来遇到address的开始标签,执行过程与前面相同;
(4)然后,遇到前面已经遇到的标签的结束标签,调用各自rule的end方法。
看个简单的例子:
public static void main(String[] args) {
String path = System.getProperty("user.dir") + File.separator + "etc";
File file = new File(path, "employee1.xml");
Digester digester = new Digester();
// add rules
digester.addObjectCreate("employee", "ex15.pyrmont.digestertest.Employee");
digester.addSetProperties("employee");
digester.addCallMethod("employee", "printName");
try {
Employee employee = (Employee) digester.parse(file);
System.out.println("First name : " + employee.getFirstName());
System.out.println("Last name : " + employee.getLastName());
}
catch(Exception e) {
e.printStackTrace();
}
}
对于要解析度目标文件,要为解析器添加Rule规则,告诉解析器当遇到规则中的几种标签元素模式时应该如何去解析,添加规则之后即可解析文件。解析器模块可以简单的分为三个子模块,Digester类、RulesBase类和Rule规则的实现类。其中Digester类是解析器类,RuleBase类并不是Rule的子类,而是一个支持类,Rule的实现类则是各种解析规则。RuleBase是Rules类的实现类,Rules是一个接口,规则了的父类Rule是一个抽象类源码注释中对Rules的定义: Public interface defining a collection of Rule instances.即Rules表示对一组Rule规则类集合的定义。
String path = System.getProperty("user.dir") + File.separator + "etc";
File file = new File(path, "employee1.xml");
Digester digester = new Digester();
// add rules
digester.addObjectCreate("employee", "ex15.pyrmont.digestertest.Employee");
digester.addSetProperties("employee");
digester.addCallMethod("employee", "printName");
try {
Employee employee = (Employee) digester.parse(file);
System.out.println("First name : " + employee.getFirstName());
System.out.println("Last name : " + employee.getLastName());
}
catch(Exception e) {
e.printStackTrace();
}
}
对于要解析度目标文件,要为解析器添加Rule规则,告诉解析器当遇到规则中的几种标签元素模式时应该如何去解析,添加规则之后即可解析文件。解析器模块可以简单的分为三个子模块,Digester类、RulesBase类和Rule规则的实现类。其中Digester类是解析器类,RuleBase类并不是Rule的子类,而是一个支持类,Rule的实现类则是各种解析规则。RuleBase是Rules类的实现类,Rules是一个接口,规则了的父类Rule是一个抽象类源码注释中对Rules的定义: Public interface defining a collection of Rule instances.即Rules表示对一组Rule规则类集合的定义。
Digester中有一个成员变量Rules rules = null;默认实现是RulesBase类。以及一个栈的实例 protected ArrayStack stack = new ArrayStack();,stack用于存放已经解析得到实例化的对象。RulesBase中有两个比较重要的成员变量属性:
protected HashMap cache = new HashMap();
protected ArrayList rules = new ArrayList();cache用来存放同一种模式的Rule规则链表类,rules就是Rule规则链表。同一种模式都会使用同一个键值放到map中去,比如digester.addObjectCreate("employee", "ex15.pyrmont.digestertest.Employee");
digester.addSetProperties("employee");
digester.addCallMethod("employee", "printName");
digester.addSetProperties("employee");
digester.addCallMethod("employee", "printName");
这三个规则都会使用同一个链表,键值为"employee",list中存放着三种模式。
首先,Digester添加规则:public void addObjectCreate(String pattern, String className) {
addRule(pattern,
new ObjectCreateRule(className));
}
addRule中new一个新的规则类
public void addRule(String pattern, Rule rule) {
rule.setDigester(this);
getRules().add(pattern, rule);
}
rule.setDigester(this);
getRules().add(pattern, rule);
}
getRules返回Digester对象的Rules实现类,默认为RulesBase,其add方法如下:
public void add(String pattern, Rule rule) {
// to help users who accidently add '/' to the end of their patterns
int patternLength = pattern.length();
if (patternLength>1 && pattern.endsWith("/")) {
pattern = pattern.substring(0, patternLength-1);
}
List list = (List) cache.get(pattern);
if (list == null) {
list = new ArrayList();
cache.put(pattern, list);
}
list.add(rule);
rules.add(rule);
if (this.digester != null) {
rule.setDigester(this.digester);
}
if (this.namespaceURI != null) {
rule.setNamespaceURI(this.namespaceURI);
}
}
此外,这些类包含有对象引用来进行关系的关联,RulesBase和Rule中的Digester的引用则用于对象之间的关联。看下ObjectCreateRule类的实现:
// to help users who accidently add '/' to the end of their patterns
int patternLength = pattern.length();
if (patternLength>1 && pattern.endsWith("/")) {
pattern = pattern.substring(0, patternLength-1);
}
List list = (List) cache.get(pattern);
if (list == null) {
list = new ArrayList();
cache.put(pattern, list);
}
list.add(rule);
rules.add(rule);
if (this.digester != null) {
rule.setDigester(this.digester);
}
if (this.namespaceURI != null) {
rule.setNamespaceURI(this.namespaceURI);
}
}
此外,这些类包含有对象引用来进行关系的关联,RulesBase和Rule中的Digester的引用则用于对象之间的关联。看下ObjectCreateRule类的实现:
ObjectCreateRule继承自Rule类,主要有begin方法和end方法用于说明Digester解析器解析相应xml文件时要执行的操作。
public void begin(Attributes attributes) throws Exception {
// Identify the name of the class to instantiate
String realClassName = className;
if (attributeName != null) {
String value = attributes.getValue(attributeName);
if (value != null) {
realClassName = value;
}
}
if (digester.log.isDebugEnabled()) {
digester.log.debug("[ObjectCreateRule]{" + digester.match +
"}New " + realClassName);
}
// Instantiate the new object and push it on the context stack
Class clazz = digester.getClassLoader().loadClass(realClassName);
Object instance = clazz.newInstance();
digester.push(instance);
}
// Identify the name of the class to instantiate
String realClassName = className;
if (attributeName != null) {
String value = attributes.getValue(attributeName);
if (value != null) {
realClassName = value;
}
}
if (digester.log.isDebugEnabled()) {
digester.log.debug("[ObjectCreateRule]{" + digester.match +
"}New " + realClassName);
}
// Instantiate the new object and push it on the context stack
Class clazz = digester.getClassLoader().loadClass(realClassName);
Object instance = clazz.newInstance();
digester.push(instance);
}
实例化相应的模式类,并调用digester对象的push方法push到栈。end方法则将对象从digester的栈中pop。
另外说明下,DIgester是使用了Sax进行xml文件的解析,因此Digester类中还有一些Sax的内容比如SaxFactory以praser等等。
另外说明下,DIgester是使用了Sax进行xml文件的解析,因此Digester类中还有一些Sax的内容比如SaxFactory以praser等等。
SetPropertiesRule类:
public void begin(Attributes attributes) throws Exception {
// Populate the corresponding properties of the top object
Object top = digester.peek();
if (digester.log.isDebugEnabled()) {
if (top != null) {
digester.log.debug("[SetPropertiesRule]{" + digester.match +
"} Set " + top.getClass().getName() +
" properties");
} else {
digester.log.debug("[SetPropertiesRule]{" + digester.match +
"} Set NULL properties");
}
}
// set up variables for custom names mappings
int attNamesLength = 0;
if (attributeNames != null) {
attNamesLength = attributeNames.length;
}
int propNamesLength = 0;
if (propertyNames != null) {
propNamesLength = propertyNames.length;
}
for (int i = 0; i < attributes.getLength(); i++) {
String name = attributes.getLocalName(i);
if ("".equals(name)) {
name = attributes.getQName(i);
}
String value = attributes.getValue(i);
// we'll now check for custom mappings
for (int n = 0; n<attNamesLength; n++) {
if (name.equals(attributeNames[n])) {
if (n < propNamesLength) {
// set this to value from list
name = propertyNames[n];
} else {
// set name to null
// we'll check for this later
name = null;
}
break;
}
}
if (digester.log.isDebugEnabled()) {
digester.log.debug("[SetPropertiesRule]{" + digester.match +
"} Setting property '" + name + "' to '" +
value + "'");
}
IntrospectionUtils.setProperty(top, name, value);
}
}
// Populate the corresponding properties of the top object
Object top = digester.peek();
if (digester.log.isDebugEnabled()) {
if (top != null) {
digester.log.debug("[SetPropertiesRule]{" + digester.match +
"} Set " + top.getClass().getName() +
" properties");
} else {
digester.log.debug("[SetPropertiesRule]{" + digester.match +
"} Set NULL properties");
}
}
// set up variables for custom names mappings
int attNamesLength = 0;
if (attributeNames != null) {
attNamesLength = attributeNames.length;
}
int propNamesLength = 0;
if (propertyNames != null) {
propNamesLength = propertyNames.length;
}
for (int i = 0; i < attributes.getLength(); i++) {
String name = attributes.getLocalName(i);
if ("".equals(name)) {
name = attributes.getQName(i);
}
String value = attributes.getValue(i);
// we'll now check for custom mappings
for (int n = 0; n<attNamesLength; n++) {
if (name.equals(attributeNames[n])) {
if (n < propNamesLength) {
// set this to value from list
name = propertyNames[n];
} else {
// set name to null
// we'll check for this later
name = null;
}
break;
}
}
if (digester.log.isDebugEnabled()) {
digester.log.debug("[SetPropertiesRule]{" + digester.match +
"} Setting property '" + name + "' to '" +
value + "'");
}
IntrospectionUtils.setProperty(top, name, value);
}
}
0 0
- Tomcat源码阅读四:Digester工具
- tomcat源码阅读之Digester
- tomcat源码阅读(二) Digester方法详解
- tomcat源码阅读步骤四
- tomcat源码中Digester解析
- Tomcat源码阅读(四)Server
- Tomcat 源码阅读(四)Connector
- Tomcat源码阅读系列(四)Connector连接器
- tomcat解析(七)Digester(四)characters,endElement.endDocument
- tomcat源码解读一 Digester的解析方式
- log4j源码阅读四
- pg源码阅读四
- STL源码阅读(四)
- tomcat源码阅读-1
- tomcat源码阅读-2
- tomcat源码阅读-3.1
- Tomcat源码阅读计划
- Tomcat源码阅读
- BeeFramework框架学习之三(底部菜单栏的实现之一)
- I学霸官方免费教程七:Java基础之类和对象
- 学习资料
- linux3.2.0块设备及nandflash驱动框架
- 【数据结构与算法】折半查找算法(二分法)
- Tomcat源码阅读四:Digester工具
- js基础
- Google 收购 Android 十周年 全面解读Android现状
- linux环境下如何对oracle数据库进行整库备份
- 微软牛津项目:图像搜索
- EventBus使用详解(一)——初步使用EventBus
- 求解!
- 极光推送相关步骤
- linux.6.5+cacti.0.8.7. 的安装记录