apache的Digester库是专门用解析管理xml文档,在tomcat中也使用了这个第三方类库来解析xml文档,也就是对应的server.xml和web.xml
org.apache.commons.digester.Digester类是Digester库的主类,该类可以用来解析xml文档,对于xml文档中的每个元素,Digester对象都会检查他事先预定义的事件。在调用Digester对象parse()方法之前,需要预先定义事件来完成解析。
在之前的tomcat启动过程源码讲解的时候,我们讲过Catalina类实例的load()
Catalina,load()


protected Digester createStartDigester() {
// Initialize the digester
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();
// Ignore className on all elements
List<String> objectAttrs = new ArrayList<>();
objectAttrs.add("className");
fakeAttributes.put(Object.class, objectAttrs);
// Ignore attribute added by Eclipse for its internal tracking
List<String> contextAttrs = new ArrayList<>();
contextAttrs.add("source");
fakeAttributes.put(StandardContext.class, contextAttrs);
// Ignore Connector attribute used internally but set on Server
List<String> connectorAttrs = new ArrayList<>();
connectorAttrs.add("portOffset");
fakeAttributes.put(Connector.class, connectorAttrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true);
// Configure the actions we will be using
// 根据Server标签创建Server对象,实例是StandardServer,设置属性,并且调用前一个对象的setServer方法,将StandardServer对象设置进去
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
digester.addObjectCreate("Server/GlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources",
"setGlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
// 遇到Listener标签,根据标签上className属性上类创建对应的对象,设置对应Listener的属性并且将该对象设置到StandardServer中
digester.addRule("Server/Listener",
new ListenerCreateRule(null, "className"));
digester.addSetProperties("Server/Listener");
digester.addSetNext("Server/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
// 遇到Service标签创建StandardService对象,然后设置其属性,然后将StandardService实例设置到StandardServer中
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标签,跟上面一样创建对应的listener对象,然后设置到 StandardService对象中。
digester.addObjectCreate("Server/Service/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
//Executor
// 创建对应的Executor 然后设置到StandardService中
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");
digester.addRule("Server/Service/Connector",
new ConnectorCreateRule());
digester.addSetProperties("Server/Service/Connector",
new String[]{"executor", "sslImplementationName", "protocol"});
// 将Connecter实例添加到 StandardService中
digester.addSetNext("Server/Service/Connector",
"addConnector",
"org.apache.catalina.connector.Connector");
digester.addRule("Server/Service/Connector", new AddPortOffsetRule());
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
digester.addSetNext("Server/Service/Connector/SSLHostConfig",
"addSslHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
new CertificateCreateRule());
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/Certificate", new String[]{"type"});
digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
"addCertificate",
"org.apache.tomcat.util.net.SSLHostConfigCertificate");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
"setOpenSslConf",
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
"addCmd",
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
digester.addObjectCreate("Server/Service/Connector/Listener",
null, // MUST be specified in the element
"className");
// 创建Connector 内部的listener
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
digester.addSetNext("Server/Service/Connector/UpgradeProtocol",
"addUpgradeProtocol",
"org.apache.coyote.UpgradeProtocol");
// Add RuleSets for nested elements
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;
}
创建对象
public void addObjectCreate(String pattern, String className)
public void addObjectCreate(String pattern, Class clazz)
public void addObjectCreate(String pattern, String className,String attributeName)
public void addObjectCreate(String pattern,String attributeName,Class clazz)
设置属性
public void addSetProperties(String pattern)
public void addSetProperties(String pattern,String attributeName,String propertyName)
public void addSetProperties(String pattern,String [] attributeNames,String [] propertyNames)
public void addSetProperty(String pattern, String name, String value)
调用方法
public void addCallMethod(String pattern, String methodName)
创建对象之间的关系
public void addSetNext(String pattern, String methodName)
public void addSetNext(String pattern, String methodName,String paramType)
向Digester类中再添加规则
public void addRuleSet(RuleSet ruleSet)
Rule.java
Rule类也是Digester中比较重要的类,包含了一些常用的方法,比如begin(),body(),end()等,当Digester对象解析到标签开始的时候会调用begin()方法,到标签内会调用body()方法,在标签末位的时候会调用end()方法。我们可以查看下addObjectCreate方法看看,该方法如何实现。

public void addRule(String pattern, Rule rule) {
rule.setDigester(this);
getRules().add(pattern, rule);
}
public Rules getRules() {
if (this.rules == null) {
this.rules = new RulesBase();
this.rules.setDigester(this);
}
return this.rules;
}
addRule是往Digester内部的一个对象rules中添加了一条rule,而其中rules指向的是一个RuleBase对象
RuleBase.java
RuleBase代表Digester类包含的所有规则集合, RuleBase内部有个HashMap存放着所有的规则,map的key是匹配规则,值是该规则对应的所有Rule的集合。

@Override
public void add(String pattern, Rule rule) {
// to help users who accidentally add '/' to the end of their patterns
int patternLength = pattern.length();
if (patternLength>1 && pattern.endsWith("/")) {
pattern = pattern.substring(0, patternLength-1);
}
List<Rule> 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);
}
}
ConnectorCreateRule.java
继承了Rule对象,复写了begin方法
@Override
public void begin(String namespace, String name, Attributes attributes)
throws Exception {
Service svc = (Service) digester.peek();
Executor ex = null;
String executorName = attributes.getValue("executor");
if (executorName != null ) {
ex = svc.getExecutor(executorName);
}
String protocolName = attributes.getValue("protocol");
Connector con = new Connector(protocolName);
if (ex != null) {
setExecutor(con, ex);
}
String sslImplementationName = attributes.getValue("sslImplementationName");
if (sslImplementationName != null) {
setSSLImplementationName(con, sslImplementationName);
}
digester.push(con);
StringBuilder code = digester.getGeneratedCode();
if (code != null) {
code.append(System.lineSeparator());
code.append(Connector.class.getName()).append(' ').append(digester.toVariableName(con));
code.append(" = new ").append(Connector.class.getName());
code.append("(new ").append(con.getProtocolHandlerClassName()).append("());");
code.append(System.lineSeparator());
if (ex != null) {
code.append(digester.toVariableName(con)).append(".getProtocolHandler().setExecutor(");
code.append(digester.toVariableName(svc)).append(".getExecutor(").append(executorName);
code.append("));");
code.append(System.lineSeparator());
}
if (sslImplementationName != null) {
code.append("((").append(AbstractHttp11JsseProtocol.class.getName()).append(">) ");
code.append(digester.toVariableName(con)).append(".getProtocolHandler()).setSslImplementationName(\"");
code.append(sslImplementationName).append("\");");
code.append(System.lineSeparator());
}
}
}
RuleSet.java

实现类

EngineRuleSet.addRuleInstances()
@Override
public void addRuleInstances(Digester digester) {
digester.addObjectCreate(prefix + "Engine",
"org.apache.catalina.core.StandardEngine",
"className");
digester.addSetProperties(prefix + "Engine");
digester.addRule(prefix + "Engine",
new LifecycleListenerRule
("org.apache.catalina.startup.EngineConfig",
"engineConfigClass"));
digester.addSetNext(prefix + "Engine",
"setContainer",
"org.apache.catalina.Engine");
//Cluster configuration start
digester.addObjectCreate(prefix + "Engine/Cluster",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Engine/Cluster");
digester.addSetNext(prefix + "Engine/Cluster",
"setCluster",
"org.apache.catalina.Cluster");
//Cluster configuration end
digester.addObjectCreate(prefix + "Engine/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Engine/Listener");
digester.addSetNext(prefix + "Engine/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
digester.addRuleSet(new RealmRuleSet(prefix + "Engine/"));
digester.addObjectCreate(prefix + "Engine/Valve",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Engine/Valve");
digester.addSetNext(prefix + "Engine/Valve",
"addValve",
"org.apache.catalina.Valve");
}
完善创建StandardEngine对象并且设置内部各种属性和对象的引用。
HostRuleSet,ContextRuleSet 差不多