Catalina.createDigester方法详细理解

这个方法主要设置(这个方法很重要,贵在理解,虽然还没学过设计模式。。)

1、遇到<server>标签时创建StandardServer实例

   设置StandardServer类内部的相关属性

   并调用Catalina.setServer()方法设置server

2、遇到<Server>标签的子标签<Listener>==》对应匹配模式"Server/Listener"时

  创建Listener实例,创建类名通过<Listener className=要创建的全类名(包名+类名)>获取属性className的值进行创建。

 调用StandardServer的addLifecycleListener()为server添加监听器

3、<Service>标签时即匹配模式为:"Server/Service"创建StandardService实例,放入Stack栈中,调用addSetProperties方法为StandardService设置相关属性

 

digester.addSetNext("Server/Service",
                            "addService",
                            "org.apache.catalina.Service");

调用Service的parent=stack.peek(1)即Server对象的addService方法为与Server关联。

4、同2一样为Service设置监听器

5、<executor>标签时即匹配模式:"Server/Service/Executor" 生成StandardThreadExecutor实例,

   设置StandardThreadExecutor的属性

  调用其父类Service的addExecutor方法与Service关联

6、调用addRule方法如上一样,

pattern:"Server/Service/Connector"==>创建Connector实例,设置属性,调用StandardService.addConnector()。为Connector设置监听器

7、调用addRuleSet()方法

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

跟6一样

、、设置Engine

EngineRuleSet(String prefix)当遇到模式为prefix + "Engine"即"Server/Service/Engine"会在EngineRuleSet.addRuleInstances()内部调用

addObjectCreate、addSetProperties、addRule这三个方法创建StandardEngine实例,设置属性,调用Service。setContainer()方法。

创建SimpleTcpCluster实例调用Engine.setCluster()方法

给Engine添加监听器,

创建realm对象实例,调用对应方法与Engine关联。

创建AccessLogValve日志对象(将日志输出到。txt文件),设置属性,与engine关联。

、、设置host

创建StandardHost,设置属性,设置监听器:HostConfig

调用Container。addChild()在这里Container即与Engine相关联

、、设置context

创建StandardContext,设置属性,设置监听器:ContextConfig

调用Container。addChild()在这里Container即与Host相关联

创建WebappLoader,与StandardContext关联

创建StandardManager,与StandardContext关联

创建store存储类,与StandardContext关联

创建StandardSessionIdGenerator,与StandardManager关联

创建ApplicationParameter,与StandardContext关联

创建realm对象实例,与StandardContext关联

创建StandardRoot,与StandardContext关联

  context==》WebResourceRoot==StandardRoot设置

  org.apache.catalina.webresources.StandardRoot提供各种resources实现类

  创建WebResourceSet,与StandardRoot关联

  (WebResourceSet的实现类有WarResourceSet、JarResourceSet、JarWarResourceSet、DirResourceSet、FileResourceSet等)

  主要设置StandardRoot的preResources、jarResources、postResources这三个变量的实例

创建ContextResourceLink,与StandardContext关联

创建AccessLogValve,与StandardContext关联

创建StandardJarScanner,与StandardContext关联

  创建StandardJarScanFilter,与StandardJarScanner关联

创建LegacyCookieProcessor与StandardContext关联

Note:上面已经说明完的具体对象被创建的整个过程,下面是对Digester的一些方法的理解。可以忽略!


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<>();
        ArrayList<String> attrs = new ArrayList<>();
        attrs.add("className");
        fakeAttributes.put(Object.class, attrs);
        digester.setFakeAttributes(fakeAttributes);
        digester.setUseContextClassLoader(true);

        // 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.NamingResourcesImpl");
        digester.addSetProperties("Server/GlobalNamingResources");
        digester.addSetNext("Server/GlobalNamingResources",
                            "setGlobalNamingResources",
                            "org.apache.catalina.deploy.NamingResourcesImpl");

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

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

    }

addObjectCreate()//Add an "object create" rule for the specified parameters.增加对象创建规则.遇到起始标签的元素,初始化一个实例对象入栈

addSetProperties()//Add a "set properties" rule for the specified parameters.增加设置属性规则.遇到某个属性名,使用setter来赋值

digester.addSetProperties("Server");

对应标签<Server port="8005" shutdown="SHUTDOWN">

遇到匹配模式为:Server。addSetProperties方法会反射调用StandardServer对象的setPort(int) 和setShutdown(String)两个方法设置属性

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

//Add a "set next" rule for the specified parameters.增加set next规则.遇到下一标签时的动作

即反射调用方法名为methodName的方法。

digester.addSetNext("Server",
                            "setServer",
                            "org.apache.catalina.Server");当遇到<Server>标签的下一标签时被调用

addSetNext方法会调用SetNextRule.end()方法会调用这个当前top栈顶对象的parent父对象(栈顶对象的下一个元素)的setServer()方法

当StandardServer对象入栈后,栈中已经存在Catalina对象===>在Catalina.load()方法中设置了

所以StandardServer的parent父对象是Catalina,即调用Catalina.setServer()方法设置server属性。

addRule:调用rule的begin 、body、end、finish方法来解析xml,入栈和出栈给对象赋值

addRuleSet:调用addRuleInstances来解析xml标签



addObjectCreate(pattern ,className ,attributeName

1、

Add an "object create" rule for the specified parameters为指定的参数增加一个对象创建规则.

Parameters:
pattern Element matching pattern元素匹配模式
className Default Java class name to be created要创建的java类的名字
attributeName Attribute name that optionally overrides the default Java class name to be created属性名称可以覆盖要创建的默认Java类名称
获取xml文件中attributes属性名为:className所对应的值替换第二个参数

ObjectCreateRule.java类的begin(String namespace, String name, Attributes attributes)方法,这个方法将通过类名加载Class然后调用class.newInstance()生成类实例,最后放入digest的对象栈顶digester.push(instance);String realClassName = className;
        if (attributeName != null) {
            String value = attributes.getValue(attributeName);
            if (value != null) {
                realClassName = value;
            }
        }

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

这个addObjectCreate()方法又调用addRule()方法

2、

Register a new Rule matching the specified pattern. This method sets the Digester property on the rule.

Parameters:
pattern Element matching pattern
rule Rule to be registered这里的rule使用的是ObjectCreateRule

Digester.addRule(String pattern, Rule rule)

addRule(pattern, new ObjectCreateRule(className, attributeName));

public void addRule(String pattern, Rule rule) {

        rule.setDigester(this);设置digester,将保存创建的对象的实例
        getRules().add(pattern, rule);这里将会返回Rules接口的实现类。然后再调用Rules.add()来添加Rule实例

    }Note:Rules:是一个接口public interface Rules        公共接口定义规则实例的集合(和相应的匹配模式)以及匹配策略的实现,        该策略选择与解析期间发现的嵌套元素的特定模式匹配的规则。   Rule:是一个抽象类public abstract class Rule

ObjectCreateRule类的解释

Rule implementation that creates a new object and pushes it onto the object stack. When the element is complete, the object will be popped

Rule实现类,创建一个新对象并将其推送到对象堆栈上。当元素完成时,对象将被弹出

3、RuleBase.add(pattern, rule)

public void add(String pattern, Rule rule) {
        // to help users who accidently 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);
        }
        if (this.namespaceURI != null) {
            rule.setNamespaceURI(this.namespaceURI);
        }

    }

上面方法用用HashMap<String, List<Rule>>类型变量cache存放pattern和Rule集合,用rules集合存放新加入的规则rules.add(rule)

Digester.addSetProperties(String pattern)

这个方法跟addObjectCreate方法调用相似顺序如下

1addRule(pattern, new SetPropertiesRule());

2getRules().add(pattern, rule);

3RulesBase.add(pattern, rule)

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

1addRule(pattern, new SetNextRule(methodName, paramType));

2getRules().add(pattern, rule);

3RulesBase.add(pattern, rule)

注:

只有当遇到改元素的结束标签时才会将改标签代表的对象实例弹出栈。

时间: 2024-12-11 13:36:45

Catalina.createDigester方法详细理解的相关文章

详细理解“&gt;/dev/null 2&gt;&amp;1”

Linux系统中无论是crontab里面,还是平时使用的命令,经常会碰到">/dev/null 2>&1".比如说:在Crontab Job里面,如果不想发送邮件,那么有两种方法: 一是将MAILTO="", 设置为空 [[email protected] etc]# cat crontab SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO="" HOME=/

S5中新增的Array方法详细说明

ES5中新增的Array方法详细说明 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=3220 一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for循环了. ES5中新增了写数组方法,如下: forEach (js v1.6) map (js v1.6) filter (js v1.6

KMP算法详细理解

KMP算法详细理解 从昨天开始看KMP算法到今天凌晨..... 把一些知识点进行总结,其实KMP还是挺简单的(HHHHHH) 博客新地址:https://miraitowa2.top/ 1:BF(暴力匹配)算法 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢? 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符: 如

IOS--UILabel的使用方法详细

IOS--UILabel的使用方法详细 //UILabel的使用 UILabel *oneLabel = [[UILabel alloc] init]; // 最经常使用的 oneLabel.frame = CGRectMake(0, 0, 320, 200); // 设置oneLabel的位置和大小 oneLabel.text = @"我是一个UILabel哦,"; // 设置oneLabel显示的字 oneLabel.textColor = [UIColor blackColor]

对Vue.js $watch方法的理解

博主最近对着vue.js的官方教程在自学vue.js,博主自幼愚钝,在教程中真的是好多点都不太理解,接下来要说的这个$watch方法就是其中一个不太理解的点了.咱们先来看一下对于$watch方法在vue.js的API中是怎么解释的吧:观察 Vue 实例变化的一个表达式或计算属性函数.回调函数得到的参数为新值和旧值.表达式只接受监督的键路径.对于更复杂的表达式,用一个函数取代.官方示例: 1 // 键路径 2 vm.$watch('a.b.c', function (newVal, oldVal)

Canavs arcTo方法的理解

arcTo方法有四个參数 參数1,2为第一个控制点的x,y坐标,參数2为第二个控制点的坐标,參数3为绘制圆弧的半径. 起点和第一个控制点组成的延长线与第一个控制点和第二个控制点组成的延长线都是和圆弧相切的,这个圆弧也就是被夹在两条延长线中间.圆越大,两条延长线能形成的角度能夹住的圆弧就越小. 以下写了一个简单的动画帮助理解 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t

C#中Thread类中Join方法的理解(转载)

指在一线程里面调用另一线程join方法时,表示将本线程阻塞直至另一线程终止时再执行      比如 Java代码   using System; namespace TestThreadJoin { class Program { static void Main() { System.Threading.Thread x = new System.Threading.Thread(new System.Threading.ThreadStart(f1)); x.Start(); Console

【转】Asp.net中时间格式化的6种方法详细总结

1. 数据控件绑定时格式化日期方法: 代码如下: <asp:BoundColumn DataField="AddTime" HeaderText="添加时间" DataFormatString="{0:yyyy-MM-dd HH:mm}></asp:BoundColumn> <asp:BoundField DataField="AddTime" HeaderText="添加时间" Dat

用实验方法加深理解Oracle的外连接(left/right/full)和内连接(inner)

总是对Oracle的左连接.右连接以及(+)对应的外连接类型糊涂,通过实验加深对连接类型语法的理解.外连接分为三种: 1. 左外连接,对应SQL关键字:LEFT (OUTER) JOIN 2. 右外连接,对应SQL关键字:RIGHT (OUTER) JOIN 3. 全外连接,对应SQL关键字:FULL (OUTER) JOIN 左右外连接都是以一张表为基表,在显示基表所有记录外,加上另外一张表中匹配的记录.如果基表的数据在另一张表中没有记录,那么相关联的结果集行中显示为空值. 精确点说,引用MO