1. 程式人生 > >struts1原始碼學習2(initChain)

struts1原始碼學習2(initChain)

先上程式碼

protected void initChain()
        throws ServletException {
        // Parse the configuration file specified by path or resource
        try {
        //還是先從servlet配置中找chainConfig
        //預設值是chainConfig = "org/apache/struts/chain/chain-config.xml";
            String value;
            value = getServletConfig().getInitParameter("chainConfig");
            if (value != null) {
                chainConfig = value;
            }
            ConfigParser parser = new ConfigParser();
            List urls = splitAndResolvePaths(chainConfig);
            URL resource;
            for (Iterator i = urls.iterator(); i.hasNext();) {
                resource = (URL) i.next();
                log.info("Loading chain catalog from " + resource);
                parser.parse(resource);
            }
        } catch (Exception e) {
            log.error("Exception loading resources", e);
            throw new ServletException(e);
        }
    }

這段程式碼比較少,也比較簡單,就是解析chain-config.xml檔案。(如果是多個檔案,中間逗號分隔)

但是這個檔案對struts的意義暫時還不是很清楚。(看字面的話,貌似是命令鏈條,用的裝飾器模式?)

chain-config.xml檔案

<?xml version="1.0" ?>
<catalog name="struts">
    <define name="lookup"
            className="org.apache.commons.chain.generic.LookupCommand"/>
    <!-- ========== Servlet Complete Request Chain ========================= -->
    <chain name="servlet-standard">
        <!-- Establish exception handling filter -->
        <command
                className="org.apache.struts.chain.commands.ExceptionCatcher"
                catalogName="struts"
                exceptionCommand="servlet-exception"/>
        <lookup
                catalogName="struts"
                name="process-action"
                optional="false"/>
        <lookup
                catalogName="struts"
                name="process-view"
                optional="false"/>
    </chain>
    <!-- ========== Action Processing chain ======================== -->
    <chain name="process-action">
        <!-- Look up optional preprocess command -->
        <lookup
                catalogName="struts"
                name="servlet-standard-preprocess"
                optional="true"/>
        <command
                className="org.apache.struts.chain.commands.servlet.SelectLocale"/>
        <command
                className="org.apache.struts.chain.commands.servlet.SetOriginalURI"/>
        <command
                className="org.apache.struts.chain.commands.servlet.RequestNoCache"/>
        <command
                className="org.apache.struts.chain.commands.servlet.SetContentType"/>
        <command
                className="org.apache.struts.chain.commands.RemoveCachedMessages"/>
        <command
                className="org.apache.struts.chain.commands.servlet.SelectAction"/>
        <command
                className="org.apache.struts.chain.commands.servlet.AuthorizeAction"/>
        <command
                className="org.apache.struts.chain.commands.CreateActionForm"/>
        <command
                className="org.apache.struts.chain.commands.servlet.PopulateActionForm"/>
        <command
                className="org.apache.struts.chain.commands.servlet.ValidateActionForm"/>
        <command
                className="org.apache.struts.chain.commands.servlet.SelectInput"/>
        <command
                className="org.apache.struts.chain.commands.ExecuteCommand"/>
        <command
                className="org.apache.struts.chain.commands.servlet.SelectForward"/>
        <command
                className="org.apache.struts.chain.commands.SelectInclude"/>
        <command
                className="org.apache.struts.chain.commands.servlet.PerformInclude"/>
        <command
                className="org.apache.struts.chain.commands.servlet.CreateAction"/>
        <command
                className="org.apache.struts.chain.commands.servlet.ExecuteAction"/>
    </chain>
    <!-- ========== View Processing chain ======================== -->
    <chain name="process-view">
        <command
                className="org.apache.struts.chain.commands.ExecuteForwardCommand"/>
        <command
                className="org.apache.struts.chain.commands.servlet.PerformForward"/>
    </chain>
    <chain name="servlet-exception">
        <command
                className="org.apache.struts.chain.commands.servlet.ExceptionHandler"/>
        <command
                className="org.apache.struts.chain.commands.servlet.PerformForward"/>
    </chain>
</catalog>

目測還是要從

ConfigParser

這個類入手

public class ConfigParser {
    private Digester digester = null;
    private RuleSet ruleSet = null;
    private boolean useContextClassLoader = true;
    public Digester getDigester() {
        if (digester == null) {
            digester = new Digester();
            RuleSet ruleSet = getRuleSet();
            digester.setNamespaceAware(ruleSet.getNamespaceURI() != null);
            digester.setUseContextClassLoader(getUseContextClassLoader());
            digester.setValidating(false);
            digester.addRuleSet(ruleSet);
        }
        return (digester);
    }
    public RuleSet getRuleSet() {
        if (ruleSet == null) {
            ruleSet = new ConfigRuleSet();
        }
        return (ruleSet);
    }
    public void setRuleSet(RuleSet ruleSet) {
        this.digester = null;
        this.ruleSet = ruleSet;
    }
    public boolean getUseContextClassLoader() {
        return (this.useContextClassLoader);
    }
    public void setUseContextClassLoader(boolean useContextClassLoader) {

        this.useContextClassLoader = useContextClassLoader;

    }
    public void parse(Catalog catalog, URL url) throws Exception {
        Digester digester = getDigester();
        digester.clear();
        digester.push(catalog);
        digester.parse(url);
    }
    public void parse(URL url) throws Exception {
        Digester digester = getDigester();
        digester.clear();
        digester.parse(url);
    }
}

直接找到parse方法,好吧,三行,再看getDigester方法,好,裡面出現了RuleSet,目測解析就在這個

ConfigRuleSet裡面。

ConfigRuleSet程式碼(各種setget被我去掉了)

public class ConfigRuleSet extends RuleSetBase {
//貌似是分類、鏈條類?className也出現了,估計就是這裡
    private String catalogClass = "org.apache.commons.chain.impl.CatalogBase";
    private String catalogElement = "catalog";
    private String chainClass = "org.apache.commons.chain.impl.ChainBase";
    private String chainElement = "chain";
    private String classAttribute = "className";
    private String commandElement = "command";
    private String defineElement = "define";
    private String nameAttribute = "name";
    public void addRuleInstances(Digester digester) {
        // catalog用ConfigCatalogRule處理,並且將成功處理的catalog放入CatalogFactory的一個map中,此map的key是catalog的classloader
        digester.addRule("*/" + getCatalogElement(),
                         new ConfigCatalogRule(nameAttribute, catalogClass));
        digester.addSetProperties("*/" + getCatalogElement());
        //以下都是解析catalog的程式碼
        // 建立org.apache.commons.chain.impl.ChainBase這個類
        //解析chain,三個引數,第一個是匹配表示式,第二個是預設建立類名稱,第三個是當匹配表示式所在的屬性來作為類名
        digester.addObjectCreate("*/" + getChainElement(),
                                 getChainClass(),
                                 getClassAttribute());
        digester.addSetProperties("*/" + getChainElement());
        //規則ConfigRegisterRule
        digester.addRule("*/" + getChainElement(),
                         new ConfigRegisterRule(nameAttribute));

        // Add rules for a command element
        digester.addObjectCreate("*/" + getCommandElement(),
                                 null,
                                 getClassAttribute());
        digester.addSetProperties("*/" + getCommandElement());
        digester.addRule("*/" + getCommandElement(),
                         new ConfigRegisterRule(nameAttribute));

        // Add rules for a define element
        digester.addRule("*/" + getDefineElement(),
                         new ConfigDefineRule(getNameAttribute(),
                                              getClassAttribute()));

    }


}

CatalogFactory將解析後的catalog放入自身map,留作後續使用


上圖就是解析xml後的catalog物件

每個ChainBase還包含若干過Command,由於大小限制,沒有畫出來。


本文出自 “helloworld” 部落格,請務必保留此出處http://lawrence16.blog.51cto.com/1908331/1532036