知识库--Digester + ContextConfig(73)

3 篇文章 0 订阅
2 篇文章 0 订阅

Digester + ContextConfig

Unlike other types of containes, a StandardContext must have a listener. This listener configures the StandardContext instance and upon successfully doing so sets the StandardContext’s configured vaiable to true.
In previous, we use the SimpleContextConfig class as the StandardContext’s listener. This class was a very simple one whose sole purpose is to set the configured variable so that the start method of StandardContext can continue.

In a real Tomcat deployment, the standard listener for StandardContext is an instance of org.apache.catalina.startup.ContextConfig class. Unlike our humble SimpleContextConfig class, ContextConfig does a lot of useful stuff that the StandardContext instance cannot live without it. A ContextConfig instance associated with a StandardContext installs an authenticator(验证器) valve in the StandardContext’s pipeline. It also adds a certificate(证书 ) valve (of type org.apache.catalina.valves.CertificateValve) to the pipeline.

More importantly, however, the ContextConfig instance also reads and parses the default web.xml file and the** application web.xml** file and convert the XML elements to Java objects. The default web.xml file is located in the conf directory of CATALINE_HOME. It defines and maps default servlets, maps file extensions with MIME types, defines the default session timeout, and list welcome files.

The application web.xml file is the application configuration file, located in the WEB-INF directory of an application. Both files are not required. ContextConfig will continue even if none of these files is found.

The** ContextConfig creates a StandardWrapper instance for each servlet element**. Therefore, as you can see in the application accompanying, configuration is made easy. You are no longer required to instantiate a wrapper anymore.

Therefore, somewhere in your bootstrap class, you must instantiate the ContextConfig class and add it to the StandardContext by calling the addLifecycleListener method of the org.apache.catalina.Lifecycle interface.

LifecycleListener listener = new ContextConfig();
((LifeCycle)context).addLifecycleListener(listener);

//启动时触事件
The StandardContext fires the following events when it is started:

BEFORE_START_EVENT
START_EVENT
AFTER_START_EVENT

When stopped, the StandardContext fires the following events:

BEFORE_STOP_EVENT
STOP_EVENT
AFTER_STOP_EVENT

The ContextConfig class responds to two events: START_EVENT and STOP_EVENT . The lifecycleEvent method is invoked every time the StandardContext triggers an event.

//the lifecycleEvent method of ContextConfig
public void lifecycleEvent(LifecycleEvent event){
    try{
        context = (Context)event.getLifecycle();
        if(context instanceof StandardContext){
            int conextDebug = context.getDebug();
            if(contextDebug > this.debug)
                this.debug = contextDebug;
        }
    }catch(ClassCastException e){
        log(...);
        return;
    }
    //process the event that has occured
    if(event.getType().equals(Lifecycle.START_EVENT)){
        start();//很重要!!
    }else if(event.getType().equals(Lifecycle.STOP_EVENT)){
        stop();
    }
}

Notice that somewhere in its body the start method calls the defaultConfig and applicationConfig methods .

The start method of ContextConfig

    private synchronized void start(){
        if(debug > 0){
            log(...);
        }
        //reset the configured boolean
        context.setConfigured(false);
        //a flag that indeicates whether the process is still going smoothly
        ok = true;
        // Set properties based on DefaultContext
        Container container = context.getParent();
        if(!context.getOverride()){
            if(container instanceof Host){
                ((Host)container).importDefaultContext(context);
            }
            if(container instanceof Engine){
                ((Engine)container).importDefaultContext(context);
            }
        }
        //Process the default and application web.xml files
        defaultConfig();
        applicationConfig();//web.xml
        if(ok)
            validateSecurityRoles();
        //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(...);
            context.setConfigured(false);
        }
}

tips 1 The defaultConfig Method
The defaultConfig method reads and parses the default web.xml file in the %CATALINA_HOME%/conf directory.

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(...);
        return;
    }catch(IOException e){
        log(...);
        return;
    }
    //Process the default web.xml file
    synchronized(webDigester){
        try{
            InputSource is = new InputSource("file://"+file.getAbsolutePath());
            stream = new FileInputStream(file);
            is.setByteStream(stream);//byte 流
            webDigester.setDebug(getDebug());
            if(context instanceof StandardContext)
                ((StandardContext)context).setReplaceWelcomeFiles(true);
            webDigester.clear();
            webDigester.push(conext);//:-O 作为root!!
            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(...);
            ok = false;
        }finally{
            try{
                if(stream != null)
                    stream.close());
            }catch(IOException e){
                log(...);
            }
        }
    }

}

Attention The webDigester object variable references a Digester instance that have been populated with rules for processing a web.xml file.

tips 2 The applicationConfig Method

The applicationConfig method is similar to the defaultConfig method, except that it processes the application deployment descriptor. A deployment descriptor resides in the WEB-INF directory of the application directory.//小心脏

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(...);
            return;
        }
        //process the application web.xml file
        //webDigester 监视器 同步堵塞
        synchronized(webDigester){
            try{
                URL url = servletContext.getResource(Contants.ApplicationWebXml);//获取resource
                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 following…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值