先上代码
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