How Tomcat Works 15: Digester

一、概述
    前面章节中,使用hard-code来管理各component间的从属关系,如果需要改变则需要重新编译Bootstrap类。幸运的是tomcat设计者采用了更优雅的方法来管理配置,即XML文件server.xml. 这样我们只需要修改server.xml文件就可以设置tomcat。如:<context docBase='myApp' path="/myApp"/>
    Tomcat采用了开源包Digester来完成xml元素到java对象的转换。而WebApp的配置则不同,它在app内部WEB-INF下的xml文件

二、组成
  1. Rule规则
   用特定的pattern解析xml内容,生成对应的对象和路径  

        void begin(org.xml.sax.Attribute)
        void end()
        void addRule(String pattern, Rule rule)


    2. 案例
    

<employee firstName="Brant" lastName="Kobe">
        <office>
          <address streetName="Los Angle" streetNumber="10" />
        </office>
    </employee>


    3. 创建对象addObjectCreate(…),四种重载方法
  

 void addObjectCreate(String pattern, Class clazz);
    void addObjectCreate(String pattern, String className);
    void addObjectCreate(String pattern, String attributeName);
    void addObjectCreate(String pattern, Class clazz, String attributeName); // digester.addObjectCreate("employee", "com.cisco.tomcat.Employee", "streetNumber")


    4. 设置属性void addSetProperties(String pattern)
    

void addProperties(String pattern)// addSetproperties("employee")-->will call setFirstName() and setLastName()

    
    5. 设置属性

void addSetNext("employee/office", "addOffice");// 会调用employee.addOffice()方法


    解析时,会按照树形结构依次将employee和office入栈, 然后调用addSetNext()构建元素关系

三、ContextConfig介绍
   1. 作用
     ContextConfig对于standardContext有很重要的作用,比如它关联了authenticator valve, CertificateValve等,更重要的ContextConfig实例也要读取解析默认web.xml文件和webApp下的web.xml文件,并转换xml元素成java对象
    2. Web.xml的配置
    CATALINA_HOME下的默认web.xml文件定义了默认Servlets的map,MIME类型的拓展名map,定义了默认session超时时间,定义欢迎文件列表
    3. WebApp下的web.xml配置
    web.xml是应用配置文件,放在webapp的WEB-INF下面。不过他们两都不是必需文件
    4. Contextconfig功能:
    为每个servlet元素创建一个StandardWrapper,所以后续配置更方便无需手工实例化Wrapper
  5.  案例
    在bootStrap类中,可以直接code:
    

  lifecyclelistener listener = new ContextConfig();
      ((Lifecycle)context).addLifecycleListener(lisenter);


   在context的启动和关闭时会fire event, START_EVENT和STOP_EVENT。这时就会触发ContextConfig的lifecycleEvent(lifecycleEvent event),lifecycleEvent方法如下:
  

 @Override
    public void LifecycleEvent(com.cisco.tomcat.lifecycle.LifecycleEvent lifecycleEvent) {
        if(lifecycleEvent.getType().equals(Lifecycle.START_EVENT)) {
            start();
        }else {
            stop();
        }
    }


    
Start方法如下:

    

private void start() {
        ok = true;
        // 初始化,设置Engine.defaultContext, Host.defaultContext
        context.setConfigured(false);
        Container container = context.getParent();
        if (container instanceof Host) {
            ((Host) container).importDefaultContext(context);
            container = container.getParent;
        }
        if (container instanceof Engine) {
            ((Engine) container).importDefaultContext(context);
        }

        // 处理默认的web.xml和WebApp的web.xml文件
        defaultConfig();
        applicationConfig();
        if (ok) {
            validateSecurityRoles();
        }
        // 为添加的listener类扫描标签库描述符
        if (ok) {
            tldScan();
        }
        // 若需要,则配置证书暴露valve
        if (ok) {
            certificatesConfig();
        }
        // 若需要,则配置认证
        if (ok) {
            authenticatorConfig();
        }
        // 若请求后,dump下context内部的pipeline的内容
        Pipeline pipeline = context.getPipeline();
        Valve[] valves = pipeline.getValves();
        for (int i = 0; i < valves.length; i++) {
            log(" " + valves.getInfo());
        }
        // 若无其他问题引入,设置我们的App为Available状态
        if (ok) {
            context.setConfigured(true);
        } else {
            log(sm.getString("contextConfig.unavailable"));
            context.setConfigured(false);
        }
    }

defaultConfig 方法:解析%CATALINA_HOME%/conf文件夹中的web.xml
    

private void defaultConfig() {    
        // 打开默认web.xml文件
        File file = new File(Constants.DefaultWebXml);
        FileInputStream stream = new FileInputStream(file.getCanonicalPath());
        stream.close();
        InputSource is = new InputSource("file://"+file.getAbsolutePath());
        stream = new FileInputStream(file);
        is.setByteStream(stream);
        webDigester.clear();
        webDigester.push(context);
        webDigetster.parse(is);
    }


applicationConfig方法:解析APP下的WEB-INF/下的web.xml
  

 private void applicationConfig() {
         ServletContext servletContext = context.getServletContext();
         InputStream stream = servletContext.getResourceAsStream(Constants.ApplicationWebXml);
         URL url = servletContext.getResource(Constants.ApplicationWebXml);
         InputSource is = new InputSrouce(url.toExternalForm());
         is.setByteStream(stream);
         webDigester.clear();
         webDigester.push(context);
         webDigester.parse(is);         
    }


静态创建WebDigester的方法
    

private static Digester createWebDigester() {
        Digester webDigester = new Digester();
        webDigester.setValidating(true);
        URL url = ContextConfig.class.getResource(Constants.WebDtdResourcePath_22);
        webDigester.register(Constants.WebDtdPublicId_22,  url.toString());
        url = ContextConfig.class.getResource(Constants.WneDtdResourcePath_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、付费专栏及课程。

余额充值