tomcat源码解析(三)——Digester类源码解析及Rule分析

在这篇文章中主要针对tomcat源码中Rule部分的解析;这部分功能主要涉及server.xml文件加载和tomcat容器中各组件初始化的过程。在我之前的文章中《tomcat源码解析(一)——Bootstrap和Catalina启动部分》《tomcat源码解析(二)——xml解析过程分析》分别对启动过程和xml解析进行了分析。

之前的文章中遗留了几个问题,将在这篇文章中进行解答;问题如下:

1、第一篇文章启动过程中Catalina类createStartDigester中设置过程及原因。

2、第二篇文章中关于rule,调用的

rule.begin(namespaceURI, name, list);

rule.body(namespaceURI, name, bodyText);

rule.end(namespaceURI, name);

rule.finish();

的具体过程和分析方法和Digester类的stack作用。


如果对tomcat使用SAX解析xml已经了解的可以较好理解本文的思路。


对于Rule的分析首先需要查看org.apache.tomcat.util.digester.Rule的源码,内容比较简单,就不放源码内容了;从中可以看到一些比较重要的信息:

1、Rule.java是一个是抽象类,对于单继承的java来说,其子类的功能职责一目了然。

2、Rule.java类所有的方法都不是抽象方法,而且具体实现都是空的(代表其子类可以自由的选择覆盖父类的方法,也可以不覆盖)

3、Rule.java类的子类比较多,这里只介绍部分,其他的类似。


现在可以正式分析Catalina的启动部分源码createStartDigester():

关于createStartDigester的源码如下:

    /**
     * Create and configure the Digester we will be using for startup.
     */
    protected Digester createStartDigester() {
        long t1=System.currentTimeMillis();
        // Initialize the digester
        Digester digester = new Digester();
        digester.setValidating(false);
        digester.setRulesValidation(true);
        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.setClassLoader(StandardServer.class.getClassLoader());

        // Configure the actions we will be using
        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.NamingResources");
        digester.addSetProperties("Server/GlobalNamingResources");
        digester.addSetNext("Server/GlobalNamingResources",
                            "setGlobalNamingResources",
                            "org.apache.catalina.deploy.NamingResources");

        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");

        digester.addObjectCreate("Server/Service",
                                 "org.apache.catalina.core.StandardService",
                                 "className");
        digester.addSetProperties("Server/Service");
        digester.addSetNext("Server/Service",
                            "addService",
                            "org.apache.catalina.Service");

        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
        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.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, // MUST be specified in the element
                                 "className");
        digester.addSetProperties("Server/Service/Connector/Listener");
        digester.addSetNext("Server/Service/Connector/Listener",
                            "addLifecycleListener",
                            "org.apache.catalina.LifecycleListener");

        // 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/"));
        digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("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));
        digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/"));

        long t2=System.currentTimeMillis();
        if (log.isDebugEnabled())
            log.debug("Digester for server.xml created " + ( t2-t1 ));
        return (digester);

    }
以上代码的功能分析如下:

1、digester.setValidating(false);设置SAX解析xml的DTD校验和schema校验,调用源码可参考Digester类的getFactory()和Digester类的getParser();

2、digester.setRulesValidation(true);看源码中只和日志打印的功能相关,和逻辑功能无关,在后文的源码中可以看到。

3、digester.setFakeAttributes(fakeAttributes);设置需要过滤的属性,如果设置后在进行类初始化时,配置的属性不会赋值给实例化后的对象,具体功能和实现在下文中会有详细说明。

4、digester.setClassLoader(StandardServer.class.getClassLoader());由于启动时首先启动的是StandardServer,设置StandardServer所在的的classloader。

5、之后的操作可以发现实际上调用的方法分为如下几个:

digester.addObjectCreate(String pattern, String className, String attributeName)

digester.addSetProperties(String pattern)

digester.addSetNext(String pattern, String methodName, String paramType)

digester.addRule(String pattern, Rule rule)

digester.addRuleSet(RuleSet ruleSet)

到这里createStartDigester()的主体功能就算分析完了;


关于上面第5点这些方法,我们继续查看Digester类的实现源码,可以总结如下规律:

1、digester.addObjectCreate(String pattern, String className, String attributeName)实际上调用的是addRule(String pattern, Rule rule)方法;且第二个参数新创建了一个对象ObjectCreateRule(className, attributeName);

2、同理可以发现digester.addSetProperties(String pattern)调用的也是addRule(String pattern, Rule rule)方法,创建了SetPropertiesRule()对象

3、digester.addSetNext(String pattern, String methodName, String paramType)调用的也是addRule(String pattern, Rule rule)方法,创建了SetNextRule(methodName, paramType)对象</

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值