tomcat解析(八)Catalina.createStartDigester

来源:互联网 发布:淘宝店铺 关注排名 编辑:程序博客网 时间:2024/05/29 13:15

在tomcat解析(四)中我们讲到了Catalina的load及start方法启动及准备整个tomcat服务器,而这两个方法最终又将该任务交由server的initialize及start方法处理,该变更将引用Server类的实例,但初始化时为空,因此我们需要该对象实例化过程,而该过程尽在Catalina.load方法的第三步骤里(可看tomcat解析四).首先我们需要了解一下其中的createStartDigester方法,该方法内容如下:

先大概讲一下该方法的内容:

1.先实例化一个Digester类的对象,调用其setValidating、setClassLoader等方法设置其某些属性,这里不是本文的重点,因此不准备细讲。

2.调用了其addObjectCreate、addSetProperties、addSetNext、addRule及addRuleSet等方法

还记得在之前我们讲到Digester类的startElement等方法时,有一点讲到该类根据标签路径名获取到一年Rule类的List后,分别调用其begin、body及end方法,那个Rule List从何而来呢,答案即将揭晓,我们这里将通过详细讲解Digester的addObjectCreate等方法来向你揭示这些Ruler的意义。因为下面这些方法均调用多次,这里将只举例说明其作用。

如:
 

  方法内容如下:
 

    在这里将调用addRule方法,该方法如下:
     

    先看getRules(),该方法如下:

我们可以看到该方法用于实例化一个RuleBase类对象,并且可以了解该方法以后每一次调用都只返回第一次生成的对象,因此是一个单例对象,在getRule方法返回后又调用了add方法,此时调用的将是RuleBase.add方法,该方法如下

        

RuleBase类里挂有一个变量名为cache的HashMap,该Map将以pattern为key,各种继承Rule类对象组成的List为value.我们再看一下在Digester.startElement里有如下语句:

List rules = getRules().match(namespaceURI, match);

如上边的解释,getRule方法将返回单例的RuleBase对象,然后以标签路径名调用其match方法,该方法内容如下:

该方法将主要以调用lookup方法来完成获取对应Rule List的工作,lookup方法如下:

我们可以看到,该方法将以标签路径名pattern为key值,从cache中取出对应的Rule List,如果我们看一下Catalina.createStartDigester各方法调用时的传入的pattern值,你会发现是到server.xml一一匹配的,据此我们可大概地理解到这个框架的实现方式:

1.实例化Digester

2.以要解析的xml的结构为准,调用Digester类各add方法加入对应的Rule.

3.调用Digester.parse方法解析xml文件,则解析每一个标签时对每一个解析动作将触发对应Rule的begin、body及end方法。

尽管理解了该框架,但我们仍然需要看一下在Catalina.createStartDigester方法加入了哪些Rule来确定在解析该文件时服务器做了多少事及这些事对整个服务器的启动有何意义。下面我们先看一下其中几个比较重要的调用,如

1.addObjectCreate,有如下的调用

 

所加入的Rule实现类为ObjectCreateRule,该类有begin方法如下

     

    可以看到该方法内容为实例化一个类,类名可为实例化该类时初始化的className对象或在调用其begin方法时传入的Attribute对象(该对象用以表示标签的属性)里className对应的类名,实例化类后又调用digester.push()方法,我们在tomcat解析四中已看到过该方法,该方法会在digester.parse之前调用,参数为已实例化的Catalina对象。

该类又有end方法如下:

 

可以看到在解析Server的开始标签时将产生一个org.apache.catalina.core.StandardServer实例,并将之放到栈中,在结束标签时又将它从栈中取,之所以放于栈中是因为后续还要对该对象进行很多处理,如下面将讲到的

2.addSetProperties

这个方法将加入的Rule实现类为SetPropertiesRule,这里先不细讲该类啦
3.addSetNext,如
该方法将添加的实现类为SetNextRule类,该类没有begin方法,因此在解析开始标签的时候没有对应的动作,但该类有end()方法,该方法是在解析结束标签的事件方法endElement()里调用的,SetNextRule类的end()方法如下:

    

    该方法内容为:取出stack顶部的对象,再取出其前一个对象,然后调用前一个对象的方法,方法名为methodName,比如有如下的调用(事实是有的)

这段代码将在解析Server标签的时候触发,此时在栈中的对象有两个,一个是最先放入的Catalina对象,而另一个是在addSetNext调用前加入的ObjectCreateRule类所实例化的org.apache.catalina.core.StandardServer实例,因此此时调用Catalina.setServer方法,以StandardServer实例为参数。这里是一个非常巧妙的设计,通过相邻的标签来生成对应的对象,并且让上一个对象作为父对象持有另一对象,因此在加入每一个RULE的时候都必须精妙地设计加入的顺序.

4.addRule,比如:
 这个直接对某一个pattern加入对应的Rule,无也讲

5.addRuleSet,如
  

 addRuleSet代码如下:

 

可以看到又调用了RuleSet实现类的addRuleInstances方法,以EngineRuleSet为例,其addRuleInstances方法如下:

    

可以得知addRuleSet方法主要是用于为某一想同前辍的标签加入一批的Rule实现类
我们没有篇幅来说明tomcat做的每一件事,因此这里我将影响到后续服务器启动的一些Rule拿出来讲一下。

1.对<Server>标签

 

实例化了一个org.apache.catalina.core.StandardServer,并以该对象为参数调用Catalina类的setServer方法,在这里我们可以回想一下在tomcat解析四里我们说的server变量所引用的对象是如何得到的呢?该对象有一个设置方法,而该方法即是setServer,因此后续整个服务器的启动重任将落于刚刚新生的org.apache.catalina.core.StandardServer对象

2.对Service标签

 

实例化了一个org.apache.catalina.core.StandardService对象,放入栈里,并以自身为参数调用栈里上一个对象的addService方法,通过server.xml我们可以了解到<service>标签是位于<server>标签之内的,因此此时StandardService的上一个对象为StandardServer对象(该对象要到结束标签时才会被取出来,这又是一个很巧妙的设计,让xml文件里有上下级关系的两个对象实例化后又存在上下级关系,或者是互持有的关系)

3.对Engine标签有:

 

将会加下以下动作:

 

内容有:实例化org.apache.catalina.core.StandardEngine对象,实例化org.apache.catalina.startup.EngineConfig对象,以该对象为参数,调用StandardEngine的addLifecycleListener方法,以StandardEngine对象为参数,调用StandardService.setContainer方法

4.对Host标签

内容有:内容有:实例化org.apache.catalina.core.StandardHost对象,实例化org.apache.catalina.startup.HostConfig对象,以该对象为参数,调用StandardHost的addLifecycleListener方法,以StandardHost对象为参数,调用StandardEngine.addChild方法

5.对Context标签

内容有:内容有:实例化org.apache.catalina.core.StandardContext对象,实例化org.apache.catalina.startup.ContextConfig对象,以该对象为参数,调用StandardContext的addLifecycleListener方法,以StandardContext对象为参数,调用StandardHost.addChild方法

 

方法总结:自上而下地实例了一些tomcat启动及处理客户请求的处理类,其中有StandardHost(表示着一个http访问的主机)、HostConfig、StandardContext(java web中的虚拟目录)及ContextConfig等,我们后续将会介绍各个主要的启动类

原创粉丝点击