How Tomcat Works学习笔记<十四>

 

Digester

         在引导类中我们需要创建连接器、context、wrapper及其它组件,同时还需要通过调用set方法对相互之间进行关联,同时还需要为这些对象设置属性,这些都进行硬编码,那么一旦需要做任何改动都需要重新编译Bootstray类,Tomcat使用Digester来解决这个问题,把配置信息都放在xml文件当中,像server.xml、web.xml等,通过Digester把xml文件解析成java对象,xml中的元素属性被设置为解析对象的属性。

Digester

         Digester是Jakarta Commons项目下的一个开源子项目,commons-digester.jar组件主要有三个包:

1、  org.apache.commons.digester提供对基于规则的任意xml文档进行处理;

2、  org.apache.commons.digester.rss提供了一些使用Digester解析XML文档的示例;

3、  org.apache.commons.digester.xmlruls提供了一些用XML定义规则。

Digester类

         org.apache.commons.digester.Digester类Digester库中的主要类,用它来解析xml文档,对于每个xml文档中的元素Digester都会去检查是否需要做一些动作,通过它可以:

1、  创建对象;

2、  设置属性;

3、  调用方法;

4、  创建对象关系;

5、  验证XML文档。

Digester操作都是通过Rule来实现的。

Rule类

         当Digester实例遇到一个XML元素开始的时候,它就会调用匹配Rule的begin方法,当Digester实例遇到一个XML元素结束的时候,它就会调用匹配Rule模式的end方法。这些Rule是在Digester创建对象、调用方法、创建对象关系的时候通过调用addRule方法添加的。

ContextConfig

         在Catalina的容器中,与其他容器不同的是StandardContext容器必须要有一个监听器,监听器会配置StandardContext实例,并把configred属性置为true,在Tomcat中这个监听器就是ContextConfig,它会给StandardContext分配认证器value、认证value给StandardContext的管道。

         同时ContextConfig实例会去解析Tomcat默认web.xml和应用部署web.xml,并跟进其中的配置生成相应的Java对象。默认web.xml中定义了在CATALINA_HOME路径下的conf目录中,它定义了一些默认的servlet及其映射,映射文件MIME类型,欢迎文件列表等,应用文件放在WEB-INF目录下,ContextConfig会为每一个servlet创建一个StandardWrapper,在启动时只需要把ContextConfig加入到StandardContext的监听器中即可:

         LifecycleListener listener = new ContextConfig();

((Lifecycle) context).addLifecycleListener(listener);

         ContextConfig会处理StandardContext的START_EVENT和STOP_EVENT事件:

         public void lifecycleEvent(LifecycleEvent event) {

        // Identify the context we are associated with

        try {

            context = (Context) event.getLifecycle();

            if (context instanceof StandardContext) {

                int contextDebug = ((StandardContext) context).getDebug();

                if (contextDebug > this.debug)

                    this.debug = contextDebug;

            }

        } catch (ClassCastException e) {

            log(sm.getString("contextConfig.cce", event.getLifecycle()), e);

            return;

        }

        // Process the event that has occurred

        if (event.getType().equals(Lifecycle.START_EVENT))

            start();

        else if (event.getType().equals(Lifecycle.STOP_EVENT))

            stop();

}

    根据事件它会去调用start和stop方法。

    start实现如下:

    private synchronized void start() {

        if (debug > 0)

            log(sm.getString("contextConfig.start"));

        context.setConfigured(false);

        ok = true;

        // Set properties based on DefaultContext

        Container container = context.getParent();

        if( !context.getOverride() ) {

            if( container instanceof Host ) {

                ((Host)container).importDefaultContext(context);

                container = container.getParent();

            }

            if( container instanceof Engine ) {

                ((Engine)container).importDefaultContext(context);

            }

        }

        // Process the default and application web.xml files

        defaultConfig();

        applicationConfig();

        if (ok) {

            validateSecurityRoles();

        }

        // Scan tag library descriptor files for additional listener classes

        if (ok) {

            try {

                tldScan();

            } catch (Exception e) {

                log(e.getMessage(), e);

                ok = false;

            }

        }

        // Configure a certificates exposer valve, if required

        if (ok)

            certificatesConfig();

        // Configure an authenticator if we need one

        if (ok)

            authenticatorConfig();

        // Dump the contents of this pipeline if requested

        if ((debug >= 1) && (context instanceof ContainerBase)) {

            log("Pipline Configuration:");

            Pipeline pipeline = ((ContainerBase) context).getPipeline();

            Valve valves[] = null;

            if (pipeline != null)

                valves = pipeline.getValves();

            if (valves != null) {

                for (int i = 0; i < valves.length; i++) {

                    log("  " + valves[i].getInfo());

                }

            }

            log("======================");

        }

        // Make our application available if no problems were encountered

        if (ok)

            context.setConfigured(true);

        else {

            log(sm.getString("contextConfig.unavailable"));

            context.setConfigured(false);

        }

}

start方法中回去调用defaultConfig和applicationConfig方法,分别去解析默认web.xml和应用web.xml。

defaultConfig

private void defaultConfig() {

        // Open the default web.xml file, if it exists

        File file = new File(Constants.DefaultWebXml);

        if (!file.isAbsolute())

            file = new File(System.getProperty("catalina.base"),

                            Constants.DefaultWebXml);

        FileInputStream stream = null;

        try {

            stream = new FileInputStream(file.getCanonicalPath());

            stream.close();

            stream = null;

        } catch (FileNotFoundException e) {

            log(sm.getString("contextConfig.defaultMissing"));

            return;

        } catch (IOException e) {

            log(sm.getString("contextConfig.defaultMissing"), e);

            return;

        }

        // Process the default web.xml file

        synchronized (webDigester) {

            try {

                InputSource is =

                    new InputSource("file://" + file.getAbsolutePath());

                stream = new FileInputStream(file);

                is.setByteStream(stream);

                webDigester.setDebug(getDebug());

                if (context instanceof StandardContext)

                    ((StandardContext) context).setReplaceWelcomeFiles(true);

                webDigester.clear();

                webDigester.push(context);

                webDigester.parse(is);

            } catch (SAXParseException e) {

                log(sm.getString("contextConfig.defaultParse"), e);

                log(sm.getString("contextConfig.defaultPosition",

                                 "" + e.getLineNumber(),

                                 "" + e.getColumnNumber()));

                ok = false;

            } catch (Exception e) {

                log(sm.getString("contextConfig.defaultParse"), e);

                ok = false;

            } finally {

                try {

                    if (stream != null) {

                        stream.close();

                    }

                } catch (IOException e) {

                    log(sm.getString("contextConfig.defaultClose"), e);

                }

            }

        }

}

applicationConfig

    private void applicationConfig() {

        // Open the application web.xml file, if it exists

        InputStream stream = null;

        ServletContext servletContext = context.getServletContext();

        if (servletContext != null)

            stream = servletContext.getResourceAsStream

                (Constants.ApplicationWebXml);

        if (stream == null) {

            log(sm.getString("contextConfig.applicationMissing"));

            return;

        }

        // Process the application web.xml file

        synchronized (webDigester) {

            try {

                URL url =

                    servletContext.getResource(Constants.ApplicationWebXml);

 

                InputSource is = new InputSource(url.toExternalForm());

                is.setByteStream(stream);

                webDigester.setDebug(getDebug());

                if (context instanceof StandardContext) {

                    ((StandardContext) context).setReplaceWelcomeFiles(true);

                }

                webDigester.clear();

                webDigester.push(context);

                webDigester.parse(is);

            } catch (SAXParseException e) {

                log(sm.getString("contextConfig.applicationParse"), e);

                log(sm.getString("contextConfig.applicationPosition",

                                 "" + e.getLineNumber(),

                                 "" + e.getColumnNumber()));

                ok = false;

            } catch (Exception e) {

                log(sm.getString("contextConfig.applicationParse"), e);

                ok = false;

            } finally {

                try {

                    if (stream != null) {

                        stream.close();

                    }

                } catch (IOException e) {

                    log(sm.getString("contextConfig.applicationClose"), e);

                }

            }

        }

}

创建web Digester

         defaultConfig和applicationConfig都会创建一个Digester:

         private static Digester createWebDigester() {

        URL url = null;

        Digester webDigester = new Digester();

        webDigester.setValidating(true);

        url = ContextConfig.class.getResource(Constants.WebDtdResourcePath_22);

        webDigester.register(Constants.WebDtdPublicId_22,

                             url.toString());

        url = ContextConfig.class.getResource(Constants.WebDtdResourcePath_23);

        webDigester.register(Constants.WebDtdPublicId_23,

                             url.toString());

        webDigester.addRuleSet(new WebRuleSet());

        return (webDigester);

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值