struts1原始碼學習2(initChain)
阿新 • • 發佈:2018-11-29
先上程式碼
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