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

本文详细介绍了如何使用Apache Digester解析Tomcat的配置文件server.xml,包括下载所需jar包、关键方法说明、注意事项、XML解析代码及Java对象代码。通过解析过程展示了如何将XML文件转换为对象,便于后续处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/wgw335363240/article/details/5869660


最近在学习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来读取的。

一、    下载Digester的jar

(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


<think>好的,我需要帮用户找到Tomcat中的conf/server.xml文件的位置。首先,我应该回忆一下Tomcat的标准目录结构。通常,Tomcat安装后会有几个主要目录,比如bin、conf、webapps等,而conf目录下存放配置文件,其中就包括server.xml。 用户可能是在自己的系统上找不到这个文件。我需要考虑不同操作系统下的默认路径。比如,在Linux系统中,如果通过包管理器安装,可能会在/etc/tomcat目录下,而手动安装的话则可能在解压后的目录里。对于Windows用户,可能是在Tomcat的安装路径下的conf文件夹里。 另外,用户可能对Tomcat的结构不太熟悉,可能需要更详细的指引。比如,是否需要说明如何通过命令行查找,或者如何在IDE中定位。比如使用find命令或者where命令,或者提示他们检查安装步骤是否正确,是否解压了Tomcat的压缩包。 还需要注意用户是否有自定义路径的情况,可能他们在安装时指定了不同的目录,这时候需要用户回忆安装时的设置。同时,可能需要提醒用户关于权限问题,比如在某些系统下需要管理员权限才能访问这些目录。 另外,查看引用的资料,引用[1]和[2]都提到了conf/server.xml中的配置,特别是Host节点和Context的配置,这说明用户可能是在配置时遇到了问题,需要找到这个文件进行修改。因此,正确的路径对他们来说很重要。 总结一下,我应该分步骤说明在不同操作系统下的默认路径,以及如何手动查找,比如通过命令行或者检查安装目录。同时,提醒用户注意自定义安装路径和权限问题,确保他们能够顺利找到文件。</think>要找到Tomcat的$conf/server.xml$文件,请按照以下步骤操作: ### 1. 默认安装路径 根据Tomcat官方目录结构,$conf$目录位于Tomcat安装根目录下。具体路径如下: - **Windows**(手动安装): $$C:\Program Files\Apache Software Foundation\Tomcat_X.X\conf\server.xml$$ - **Linux/macOS**(手动安装): $$/usr/local/tomcat_X.X/conf/server.xml$$ > 注意:`X.X`表示Tomcat版本号(如`8.5`或`10.1`) ### 2. 验证安装位置 可通过以下方式验证具体路径: - **通过启动日志**:启动Tomcat时控制台输出的`CATALINA_BASE`路径 - **命令行定位**: ```bash # Linux/macOS find / -name 'server.xml' 2>/dev/null | grep 'conf/server.xml' # Windows where /R C:\ server.xml ``` ### 3. 特殊安装情况 - **通过包管理器安装**(如Linux的`apt`): $$/etc/tomcat_X.X/server.xml$$ - **IDE集成环境**(如Eclipse/IntelliJ): 路径通常为: $$工作空间目录/.metadata/.plugins/org.eclipse.wst.server.core/tmpX/conf/server.xml$$ ### 4. 配置关联说明 该文件控制Tomcat核心参数,例如: ```xml <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> ``` 引用资料中提到的`appBase`和`docBase`配置也在此文件中定义[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值