内容简介:tomcat7中Digester的使用以及对server.xml的解析过程分析
tomcat在启动的时候,会调用Catalina的load的方法启动一个新的Server实例,在这里会有关于Digester的使用,以及对server.xml的解析过程。
load方法的代码如下:
public void load() { ... // Create and execute our Digester Digester digester = createStartDigester(); ... try { inputSource.setByteStream(inputStream); digester.push(this); digester.parse(inputSource); } ... }
代码做了精简,只保留了Digester的最重要部分。首先是创建并配置要用来启动的Digester实例,然后获取到server.xml文件的输入流之后,使用digester进行解析。
Digester介绍
在进行具体步骤的解析之前,首先看一下Digester的简单介绍,Digester用来处理xml,是对SAX的包装,所以也是基于文件流来解析xml的。Digester使用的步骤也很简单:
- 创建一个Digester实例
- 设置相关属性
- 设置具体的规则
- 调用parse方法进行解析
createStartDigester
此方法用来创建和配置Digester,对应着上面的前三个步骤,具体代码如下:
protected Digester createStartDigester() { long t1=System.currentTimeMillis(); //创建一个digester实例 Digester digester = new Digester(); //是否需要验证xml文档的合法性,false表示不需要进行DTD规则校验 digester.setValidating(false); //是否需要进行节点设置规则校验 digester.setRulesValidation(true); //将xml节点中的className作为假属性,不用调用默认的setter方法 //在解析时,调用相应对象的setter方法来设置属性值,setter的参数就是节点属性, //而有className的话,则直接使用className来直接实例化对象 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); digester.setUseContextClassLoader(true); //下面添加各种规则 //遇到xml中Server节点,就创建一个StandardServer对象 digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className"); //根据Server节点中的属性信息,调用属性的setter方法,比如说server节点中会有port=“8080”属性,则会调用setPort方法 digester.addSetProperties("Server"); //在上面的load方法中有个digester.push(this),this对象就是栈顶了 //这里将Server节点对应的对象作为参数,调用this对象,也就是Catalina对象的setServer方法 digester.addSetNext("Server", "setServer", "org.apache.catalina.Server"); //Server节点下的GlobalNamingResources节点,创建一个NamingResource对象 digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResources"); digester.addSetProperties("Server/GlobalNamingResources"); digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResources"); //Server下的Listener节点 digester.addObjectCreate("Server/Listener", null, // MUST be specified in the element "className"); digester.addSetProperties("Server/Listener"); digester.addSetNext("Server/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //Server下的Service节点 digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className"); digester.addSetProperties("Server/Service"); digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service"); //Service节点下的Listener节点 digester.addObjectCreate("Server/Service/Listener", null, "className"); digester.addSetProperties("Server/Service/Listener"); digester.addSetNext("Server/Service/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //Executor节点 digester.addObjectCreate("Server/Service/Executor", "org.apache.catalina.core.StandardThreadExecutor", "className"); digester.addSetProperties("Server/Service/Executor"); digester.addSetNext("Server/Service/Executor", "addExecutor", "org.apache.catalina.Executor"); //给Connector添加规则,就是当遇到Connector的时候,会调用ConnectorCreateRule里面定义的规则 //跟上面的作用是一样的,只不过该节点的规则比较多,就创建一个规则类 digester.addRule("Server/Service/Connector", new ConnectorCreateRule()); digester.addRule("Server/Service/Connector", new SetAllPropertiesRule(new String[]{"executor"})); digester.addSetNext("Server/Service/Connector", "addConnector", "org.apache.catalina.connector.Connector"); digester.addObjectCreate("Server/Service/Connector/Listener", null, "className"); digester.addSetProperties("Server/Service/Connector/Listener"); digester.addSetNext("Server/Service/Connector/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //给嵌入元素添加RuleSet自定义规则 //每个rule规则,都会有tomcat对自身业务逻辑的判断和处理 digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/")); digester.addRuleSet(new EngineRuleSet("Server/Service/")); digester.addRuleSet(new HostRuleSet("Server/Service/Engine/")); digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/")); addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/"); digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/")); // When the 'engine' is found, set the parentClassLoader. digester.addRule("Server/Service/Engine", new SetParentClassLoaderRule(parentClassLoader)); addClusterRuleSet(digester, "Server/Service/Engine/Cluster/"); return (digester); }
上面创建完Digester对象,并设置了属性和各种规则之后,接下来主要的就是解析工作。
parse解析
parse方法代码如下:
public Object parse(InputSource input) throws IOException, SAXException { //解析前的配置,默认什么也没做,需要子类去实现 configure(); //获取解析器去解析 getXMLReader().parse(input); return (root); }
解析完成之后,Server,Service等等在server.xml中存在的节点,就会有对应的对象存在,后续就可以使用这些对象进行初始化和启动了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning XML with DOM and Ajax
Sas Jacobs / Apress / 2006-06-05 / USD 39.99
Don't waste time on 1,000-page tomes full of syntax; this book is all you need to get ahead in XML development. Renowned web developer Sas Jacobs presents an essential guide to XML. Beginning XML with......一起来看看 《Beginning XML with DOM and Ajax》 这本书的介绍吧!