您的位置:首页 > 运维架构 > Tomcat

Tomcat源码的catalina中利用Digester解析conf/server.xml

2010-09-07 23:28 453 查看
最近在学习Tomcat的源码,在catalina. createStartDigester方法中,Tomcat开发人员采用了Digester来读取conf/server.xml文件,以前读取xml文件一般采用Dom4j和SAX。由于对Digester比较陌生,所以今天抽时间研究了一下Digester是如何解析xml文件的。先简单阐述下Dom4j和SAX解析XML的却别:
Dom4j是把一个xml文件全部读取到内存中,构建成一个DOM树来解析,所以Dom4j适合读取比较小的xml文件。
SAX是基于文件流来解析xml文件的,在读取xml文件流时,SAX会通过节点来触发相应的操作,也可以说SAX是基于文件流的事情触发机制来解析xml文件的。
Digeter是apache的common项目,作用是将XML转化成对象,使用者直接从对象中获取xml的节点信息。Digester是对SAX的包装,它也是基于文件流来解析xml文件,只不过这些解析操作对用户是透明的。Tomcat的配置文件conf/server.xml就是用Digester来读取的。
一、 下载Digesterjar
(1) Digester的jar下载地址(版本:2.0) http://commons.apache.org/digester/ (2) Digester依赖的Logging的jar下载地址(版本:1.1.1) http://commons.apache.org/logging/ (3) Digester依赖的BeanUtils的jar下载地址(版本:1.8.3)
http://commons.apache.org/beanutils/

只需要按照以上步骤下载jar包后,导入到eclipse工程即可。为了大家省去jar包下载的麻烦,我在博客资源中上传了“Digester_jar”资源,这里面包含了所有需要的jar包和源码。
对应的对象的源码参考我博客资源中的“Digester_object”资源,这里包含了测试代码中需要的Java对象代码。
二、 关键方法说明
(1) serverDigester.addObjectCreate("Server","com.test.server.digester.Server")
当解析xml文件时,遇到“Server”就初始化一个“com.test.server.digester.Server”对象,并且把该对象压入栈顶
(2) serverDigester.addSetProperties("Server", "port", "port")
给Server对象注册port属性,当解析到Server节点的port属性时调用Server的setPort方法
(3) serverDigester.addSetNext("Server/Listener", "addListener","com.test.server.digester.Listener")
当解析Server节点下的Listener节点的时候,调用Server对象的addListener方法,把当前Listener对象写入到Server对象中。无论Server节点下有多少个Listener节点,都会调用addListener方法
(4) serverDigester.addCallMethod("Server/Service/Engine", "setEngine", 0)
Service中添加Engine,调用当前top object的setEngine函数,参数个数为0
addCallMethod与addBeanPropertySetter方法等价
三、 注意事项
Xml中定义的属性要与对象中set和get方法一致,比如xml中定义了一个节点属性“engineType”,那么在java对象的set方法必须为setEngineType,除了首字母外,其他字母必须一致,不然在解析的时候会解析不到对应的属性值。不知道是否还有其他规则,没有摸清楚。
四、 XML解析代码
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Attribute must be lower case.
For example:
attribute :engineType
Method in Service must be setEngineType(All attribute character but one must be the same with method in PO!)

-->
<Server port="9996" debug="0">
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"
debug="0"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"
debug="1"/>
<Service name="Catalina">
<Engine engineType="12">I am a Engine</Engine>
</Service>
</Server>
五、 Java对象代码(也可以见博客资源“Digester_object”
(1) Server.java代码
/**
*
*/
package com.test.server.digester;

import java.util.Vector;

/**
* 模仿解析Tomcat的conf/server.xml中的节点serve类
*
* @author rey
*
*/
public class Server {

/**
*构造函数
*/
public Server() {
super();
}

// 成员变量===============================
private int m_nPort = 0;
private int m_nIsDebug = 0;
private Service m_Service = null;
private Vector m_listenerVector = new Vector();

// 公有方法=================================
/**
* @return the m_nPort
*/
public int getPort() {
return m_nPort;
}

/**
* @param mNPort
* the m_nPort to set
*/
public void setPort(int mNPort) {
m_nPort = mNPort;
}

/**
* @return the m_nIsDebug
*/
public int getIsDebug() {
return m_nIsDebug;
}

/**
* @param mNIsDebug
* the m_nIsDebug to set
*/
public void setIsDebug(int mNIsDebug) {
m_nIsDebug = mNIsDebug;
}

/**
* @return the m_service
*/
public Service getService() {
return m_Service;
}

/**
* @param mService the m_service to set
*/
public void setService(Service mService) {
m_Service = mService;
}

public void addListener(Listener _listener) {
m_listenerVector.add(_listener);
}

public Vector getListeners() {
return m_listenerVector;
}
}
(2) Service.java代码
/**
*
*/
package com.test.server.digester;

/**
* 模仿解析Tomcat的conf/server.xml中的节点Service类
*
* @author rey
*
*/
public class Service {

/**
*
*/
public Service() {
super();
}

// 成员变量===============================
private String m_sName = null;
private String m_sEngine =null;
private String m_sEngineType=null;

// 公有方法=================================

/**
* @return the m_sEngineType
*/
public String getEngineType() {
return m_sEngineType;
}

/**只能有第一个字母大写,如果还有其他的大写,则解析不出来
* @param mSEngineType the m_sEngineType to set
*/
public void setEngineType(String mSEngineType) {
m_sEngineType = mSEngineType;
}

/**
* @return the m_sEngine
*/
public String getEngine() {
return m_sEngine;
}

/**
* @param mSEngine the m_sEngine to set
*/
public void setEngine(String mSEngine) {
m_sEngine = mSEngine;
}

/**
* @return the m_sName
*/
public String getName() {
return m_sName;
}

/**
* @param mSName
* the m_sName to set
*/
public void setName(String mSName) {
m_sName = mSName;
}
}
(3) Listener代码
/**
*
*/
package com.test.server.digester;

/**
* 模仿解析Tomcat的conf/server.xml中的节点Listener类
*
* @author rey
*
*/
public class Listener {

/**
*
*/
public Listener() {
super();
}

// 成员变量===============================

private String m_sClassName = null;
private int m_nIsDebug = 0;

// 公有方法=================================
/**
* @return the m_nIsDebug
*/
public int getDebug() {
return m_nIsDebug;
}

/**
* @param mNIsDebug
* the m_nIsDebug to set
*/
public void setDebug(int mNIsDebug) {
m_nIsDebug = mNIsDebug;
}

/**
* @return the m_sClassName
*/
public String getClassName() {
return m_sClassName;
}

/**
* @param mSClassName
* the m_sClassName to set
*/
public void setClassName(String mSClassName) {
m_sClassName = mSClassName;
}
}
(4) Engine代码
/**
*
*/
package com.test.server.digester;

/**
* 模仿解析Tomcat的conf/server.xml中的节点Engine类
* @author rey
*
*/
public class Engine {

/**
*
*/
public Engine() {
super();
}

// 成员变量===============================
private String m_sName = null;
private int m_nIsDebug = 0;

// 公有方法=================================
/**
* @return the m_sName
*/
public String getName() {
return m_sName;
}

/**
* @param mSName
* the m_sName to set
*/
public void setName(String mSName) {
m_sName = mSName;
}
/**
* @return the m_nIsDebug
*/
public int getIsDebug() {
return m_nIsDebug;
}

/**
* @param mNIsDebug
* the m_nIsDebug to set
*/
public void setIsDebug(int mNIsDebug) {
m_nIsDebug = mNIsDebug;
}
}
六、 Java解析xml代码
DigesterServer代码:
/**
*
*/
package com.test.server.digester;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Vector;

import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

/**
* 用于解析Tomcat的conf/server.xml的Diagester
*
* @author rey
*
*/
public class DigesterServer {

/**
* @param args
* @throws SAXException
* @throws IOException
*/
public static void main(String[] args) throws IOException, SAXException {
String sXMLFile = "D://temp//test_diagester.xml";
Digester serverDigester = new Digester();
FileInputStream inputXMLStream = new FileInputStream(sXMLFile);

// 解析Server.xml
serverDigester.setValidating(false);

// 注册Server规则,解析XML时,遇到Server,就实例化一个com.test.server.digester.Server对象,并且压栈
serverDigester.addObjectCreate("Server",
"com.test.server.digester.Server");

//给Server对象设置一个属性,可以调用setPort进行设置
serverDigester.addSetProperties("Server", "port", "port");
serverDigester.addSetProperties("Server", "debug", "debug");

// 注册Listener规则,这里的斜线是根据xml的path来计算的
serverDigester.addObjectCreate("Server/Listener",
"com.test.server.digester.Listener");
serverDigester.addSetProperties("Server/Listener", "className",
"className");
serverDigester.addSetProperties("Server/Listener", "debug", "debug");

// Server对象添加一个Listener对象(无论Server节点下有几个Listener对象,都会添加到Vector中)
serverDigester.addSetNext("Server/Listener", "addListener",
"com.test.server.digester.Listener");

// 注册Service对象
serverDigester.addObjectCreate("Server/Service",
"com.test.server.digester.Service");
serverDigester.addSetProperties("Server/Service", "name", "name");

// server中添加Service
serverDigester.addSetNext("Server/Service", "setService",
"com.test.server.digester.Service");

// Service中添加Engine,调用当前top object的setEngine函数,参数个数为0
serverDigester.addCallMethod("Server/Service/Engine", "setEngine", 0);
serverDigester.addSetProperties("Server/Service/Engine","enginetype","enginetype");

// 开始解析XML文件
Server currServer = (Server) serverDigester.parse(inputXMLStream);
if (currServer == null) {
System.out.println("currServer==null");
return;
}
Vector listenerVector = currServer.getListeners();
System.out.println(listenerVector.size());

<span style="font-size
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: