struts2源码分析(三)(初始化)(下)
2013-09-29 11:11
537 查看
12)ActionContext oldContext = ActionContext.getContext();
获取ActionContext的实例。ActionContext的具体方法如下所示:
13)setContext(bootstrap);
调用DefaultConfiguration的setContext(Container cont)方法,其中bootstrap是一个ContainerImpl类的实例,该方法具体内容如下:
14)container = builder.create(false);
调用的是ContainerBuilder中的create方法创建一个Container对象,该方法在上面已经对其进行过介绍。
15)setContext(container);
把container添加到ActionContext中该方法与13)一样
16)objectFactory = container.getInstance(ObjectFactory.class);//获取一个objectFactory实例
17)container.inject(containerProvider);//注入到容器中
18)((PackageProvider)containerProvider).loadPackages();//调用loadPackages方法
1:DefaultPropertiesProvider(default.properties)
该类中为覆盖父类中的loadPackages()方法,此时调用父类中的loadPackages()方法如下
2:StrutsXmlConfigurationProvider(struts-default.xml)
该类中的loadPackages()方法如下:
父类XmlConfigurationProvider中的loadPackages()方法如下:
①PackageConfig cfg = addPackage(child);//解析该节点,并把解析之后的信息放入DefulatConfiguration中的packageContexts中
在这里先看了解一些重要的类
ResultConfig(com.opensymphony.xwork2.config.entities)类
InterceptorMapping(com.opensymphony.xwork2.config.entities)
ExceptionMappingConfig(com.opensymphony.xwork2.config.entities)
ResultTypeConfig(com.opensymphony.xwork2.config.entities)
ActionConfig(com.opensymphony.xwork2.config.entities)
PackageConfig(com.opensymphony.xwork2.config.entities)
这个方法中所需的类基本介绍完了,下面介绍解析过程;在此调用XmlConfigurationProvider类的addPackage(Element packageElement)方法,该方法具体内容如下:
在这里对其具体代码进行分析:
//为这个package添加result types 和默认的result
addResultTypes(newPackage, packageElement);该方法的具体代码如下:
//为这个package添加interceptors和interceptor stacks
loadInterceptors(newPackage, packageElement);该方法具体内容如下:
在该方法中又调用了设置InterceptorStacks的方法,该方法具体如下:
在该方法内部调用了loadInterceptorStack方法,该方法具体如下:
在该方法内部调用lookupInterceptorReference方法,该方法具体内容如下:
至此该package的InterceptorStack加载完成
//为这个package添加默认的interceptors
loadDefaultInterceptorRef(newPackage, packageElement);
//为这个package添加默认的default-class-ref
loadDefaultClassRef(newPackage, packageElement);
//为package添加全局results
loadGlobalResults(newPackage, packageElement);
//为这个package添加全局的exception
loadGobalExceptionMappings(newPackage, packageElement);
NodeList actionList = packageElement.getElementsByTagName("action");//查找所有的action节点
//把该action元素添加到package中
addAction(actionElement, newPackage);
在这个方法内部调用了buildResult(Element element, PackageConfig.Builder packageContext)方法,该方法具体如下:
为该action添加拦截器
为该action添加异常映射
为该action添加allow-method
这些配置完成之后,把该action添加到packageContext中
然后调用:
//为该package加载默认的action
loadDefaultActionRef(newPackage, packageElement);
在然后实例化该packageConfig对象,并添加到DefaultConfiguration中,返回该defaultConfiguration
②reloads.add(child);
如果配置需要重新更新的话,重新加载该package节点
③loadExtraConfiguration(doc);
该方法未执行任何操作,该方法内容具体如下:
③loadExtraConfiguration(doc);//这三个方法没什么好介绍的
④reloadRequiredPackages(reloads);
⑤loadExtraConfiguration(doc);
至此,loadPackages方法执行结束
3:StrutsXmlConfigurationProvider(struts-plugin.xml)
同2:
4:StrutsXmlConfigurationProvider(struts.xml)
同2:
5:LegacyPropertiesConfigurationProvider
同1:
6:用户配置
具体情况具体分析
7:web.xml的filter中配置的参数
该方法是一个空实现
8:BeanSelectionProvider
该类中的该方法是一个空实现
19)packageProviders.add((PackageProvider)containerProvider);
把解析完之后的packageProvider放入packageProviders的list中
20)Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
根据类型来取得该类型的实例对象名称集合(适用于同一个类型创建了多个不同名称的对象)
21)PackageProvider provider = container.getInstance(PackageProvider.class, name);
22)provider.init(this);
23)provider.loadPackages();
24)packageProviders.add(provider);
25)rebuildRuntimeConfiguration();
27)return packageProviders;
这些代码,暂时未分析
②Container container = config.getContainer();
获取DefaultConfiguration实体对象的Container对象(此时的Container对象是一个ContainerImpl对象)
③boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
获取是否配置了国际化
④LocalizedTextUtil.setReloadBundles(reloadi18n);
定义是否需要重新装载资源绑定
4、加载完配置文件之后执行的操作
一:container.inject(this);
二:init_CheckConfigurationReloading(container);
三:init_CheckWebLogicWorkaround(container);
5、介绍StrutsPrepareAndExecuteFilter中剩余的部分
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);实例化一个prepare方法
这里的PrepareOperations类的构造方法如下:
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);实例化一个execute方法
这里的ExecuteOperations类的构造方法如下:
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);执行buildExcludedPatternsList方法
该方法的具体含义目前不是很了解
postInit(dispatcher, filterConfig);//执行postInit方法
调用的StrutsPrepareAndExecuteFilter类中的postInit(Dispatcher dispatcher, FilterConfig filterConfig)方法如下:
至此,struts2框架初始化结束
获取ActionContext的实例。ActionContext的具体方法如下所示:
/** * 返回特定于当前线程的ActionContext * @return ActionContext 当前线程的ActionContext */ public static ActionContext getContext() { return (ActionContext) actionContext.get(); }
13)setContext(bootstrap);
调用DefaultConfiguration的setContext(Container cont)方法,其中bootstrap是一个ContainerImpl类的实例,该方法具体内容如下:
/** * 判断当前ActoinContext的getContext是否存在,如果不存在则创建一个并返回 * @param cont * @return */ protected ActionContext setContext(Container cont) { //获取当前ActionContext ActionContext context = ActionContext.getContext(); //判断当前ActionContext是否为空 if (context == null) { //若为空的话,则新建一个放入ActionContext中(ValueStack未分析) ValueStack vs = cont.getInstance(ValueStackFactory.class).createValueStack();//从ContainerBuilder中获取一个创建ValueStack的工厂类,并创建一个ValueStack实例 context = new ActionContext(vs.getContext());//创建一个新的ActionContext对象 ActionContext.setContext(context);//添加到ActionContext中 } return context;//返回当前的ActionContext }
14)container = builder.create(false);
调用的是ContainerBuilder中的create方法创建一个Container对象,该方法在上面已经对其进行过介绍。
15)setContext(container);
把container添加到ActionContext中该方法与13)一样
16)objectFactory = container.getInstance(ObjectFactory.class);//获取一个objectFactory实例
17)container.inject(containerProvider);//注入到容器中
18)((PackageProvider)containerProvider).loadPackages();//调用loadPackages方法
1:DefaultPropertiesProvider(default.properties)
该类中为覆盖父类中的loadPackages()方法,此时调用父类中的loadPackages()方法如下
/** * 加载包,但是在该类里面不执行 */ public void loadPackages() throws ConfigurationException { }
2:StrutsXmlConfigurationProvider(struts-default.xml)
该类中的loadPackages()方法如下:
/* (non-Javadoc) * @see com.opensymphony.xwork2.config.providers.XmlConfigurationProvider#init(com.opensymphony.xwork2.config.Configuration) */ @Override public void loadPackages() { ActionContext ctx = ActionContext.getContext(); ctx.put(reloadKey, Boolean.TRUE);//向ActionContext中添加一个一个Map super.loadPackages();//调用父类的loadPackages()方法 }
父类XmlConfigurationProvider中的loadPackages()方法如下:
/** * 对*.xml中的package进行解析 */ public void loadPackages() throws ConfigurationException { List<Element> reloads = new ArrayList<Element>(); //对documents进行遍历 for (Document doc : documents) { Element rootElement = doc.getDocumentElement();//获取根元素 NodeList children = rootElement.getChildNodes();//获取所有子节点 int childSize = children.getLength();//获取子节点的长度 /** * 对子节点进行遍历 */ for (int i = 0; i < childSize; i++) { Node childNode = children.item(i);//获取第I个子节点 if (childNode instanceof Element) { Element child = (Element) childNode;//把节点转换成元素 final String nodeName = child.getNodeName();//获取元素的name //如果该元素名为package if ("package".equals(nodeName)) { ①PackageConfig cfg = addPackage(child);//解析该节点,并把解析之后的信息放入DefulatConfiguration中的packageContexts中 if (cfg.isNeedsRefresh()) { ②reloads.add(child); } } } } ③loadExtraConfiguration(doc); } if (reloads.size() > 0) { ④reloadRequiredPackages(reloads); } for (Document doc : documents) { ⑤loadExtraConfiguration(doc); } //清空documents documents.clear(); configuration = null;//设置configuration为空 }
①PackageConfig cfg = addPackage(child);//解析该节点,并把解析之后的信息放入DefulatConfiguration中的packageContexts中
在这里先看了解一些重要的类
ResultConfig(com.opensymphony.xwork2.config.entities)类
/** * 结果的配置,在xml的配置文件中像定义一个result标签一样 */ public class ResultConfig extends Located implements Serializable { protected Map<String,String> params;//参数 protected String className;//结果名 protected String name;//结果名称 /** * 根据给定的name和className实例化一个ResultConfig对象 * @param name 结果名称 * @param className 结果名 */ protected ResultConfig(String name, String className) { this.name = name; this.className = className; params = new LinkedHashMap<String, String>(); } /** * 根据给定的一个ResultConfig对象复制一个新的对象 * @param orig */ protected ResultConfig(ResultConfig orig) { this.params = orig.params; this.name = orig.name; this.className = orig.className; } /** * 获取className * @return */ public String getClassName() { return className; } /** * 获取name * @return */ public String getName() { return name; } /** * 获取param * @return */ public Map<String,String> getParams() { return params; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof ResultConfig)) { return false; } final ResultConfig resultConfig = (ResultConfig) o; if ((className != null) ? (!className.equals(resultConfig.className)) : (resultConfig.className != null)) { return false; } if ((name != null) ? (!name.equals(resultConfig.name)) : (resultConfig.name != null)) { return false; } if ((params != null) ? (!params.equals(resultConfig.params)) : (resultConfig.params != null)) { return false; } return true; } @Override public int hashCode() { int result; result = ((name != null) ? name.hashCode() : 0); result = (29 * result) + ((className != null) ? className.hashCode() : 0); result = (29 * result) + ((params != null) ? params.hashCode() : 0); return result; } /** * 这个类的builder方法。唯一创建该类的实例的方法。目的是为了维持执行对象的不变性。 * 该方式是通过结构化的方式来至此chain方式。设置完需要的参数之后,可以调用build方法创建一个实例 */ public static final class Builder { protected ResultConfig target;//创建一个对象 /** * 实例化该对象 * @param name * @param className */ public Builder(String name, String className) { target = new ResultConfig(name, className); } /** * 复制一个该对象 * @param orig */ public Builder(ResultConfig orig) { target = new ResultConfig(orig); } /** * 设定该对象的名称 * @param name * @return */ public Builder name(String name) { target.name = name; return this; } /** * 设定该对象的结果明 * @param name * @return */ public Builder className(String name) { target.className = name; return this; } /** * 添加一个参数 * @param name * @param value * @return */ public Builder addParam(String name, String value) { target.params.put(name, value); return this; } /** * 添加一个map类型的参数集合 * @param params * @return */ public Builder addParams(Map<String,String> params) { target.params.putAll(params); return this; } /** * 设置该对象的location * @param loc * @return */ public Builder location(Location loc) { target.location = loc; return this; } /** * 创建该对象 * @return */ public ResultConfig build() { embalmTarget(); ResultConfig result = target; target = new ResultConfig(target); return result; } protected void embalmTarget() { target.params = Collections.unmodifiableMap(target.params); } } }
InterceptorMapping(com.opensymphony.xwork2.config.entities)
/** * 拦截器Mapping */ public class InterceptorMapping implements Serializable { private String name;//拦截器名 private Interceptor interceptor;//拦截器实现类 public InterceptorMapping(String name, Interceptor interceptor) { this.name = name; this.interceptor = interceptor; } public String getName() { return name; } public Interceptor getInterceptor() { return interceptor; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final InterceptorMapping that = (InterceptorMapping) o; if (name != null ? !name.equals(that.name) : that.name != null) return false; return true; } @Override public int hashCode() { int result; result = (name != null ? name.hashCode() : 0); return result; } }
ExceptionMappingConfig(com.opensymphony.xwork2.config.entities)
/** * 异常映射的配置 */ public class ExceptionMappingConfig extends Located implements Serializable { protected String name;//名称 protected String exceptionClassName;//异常类名称 protected String result;//结果 protected Map<String,String> params;//参数 /** * 初始化一个ExceptionMappingConfig对象 * @param name 名称 * @param exceptionClassName 异常类名称 * @param result 结果 */ protected ExceptionMappingConfig(String name, String exceptionClassName, String result) { this.name = name; this.exceptionClassName = exceptionClassName; this.result = result; this.params = new LinkedHashMap<String,String>(); } /** * 根据现有的一个ExceptionMappingConfig实例化一个新的ExceptionMappingConfig对象 * @param target */ protected ExceptionMappingConfig(ExceptionMappingConfig target) { this.name = target.name; this.exceptionClassName = target.exceptionClassName; this.result = target.result; this.params = new LinkedHashMap<String,String>(target.params); } /** * 获取名称 * @return */ public String getName() { return name; } /** * 获取异常类名称 * @return */ public String getExceptionClassName() { return exceptionClassName; } /** * 获取结果 * @return */ public String getResult() { return result; } /** * 获取参数集合 * @return */ public Map<String,String> getParams() { return params; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof ExceptionMappingConfig)) { return false; } final ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) o; if ((name != null) ? (!name.equals(exceptionMappingConfig.name)) : (exceptionMappingConfig.name != null)) { return false; } if ((exceptionClassName != null) ? (!exceptionClassName.equals(exceptionMappingConfig.exceptionClassName)) : (exceptionMappingConfig.exceptionClassName != null)) { return false; } if ((result != null) ? (!result.equals(exceptionMappingConfig.result)) : (exceptionMappingConfig.result != null)) { return false; } if ((params != null) ? (!params.equals(exceptionMappingConfig.params)) : (exceptionMappingConfig.params != null)) { return false; } return true; } @Override public int hashCode() { int hashCode; hashCode = ((name != null) ? name.hashCode() : 0); hashCode = (29 * hashCode) + ((exceptionClassName != null) ? exceptionClassName.hashCode() : 0); hashCode = (29 * hashCode) + ((result != null) ? result.hashCode() : 0); hashCode = (29 * hashCode) + ((params != null) ? params.hashCode() : 0); return hashCode; } /** * 这个类的builder方法。唯一创建该类的实例的方法。目的是为了维持执行对象的不变性。 * 该方式是通过结构化的方式来至此chain方式。设置完需要的参数之后,可以调用build方法创建一个实例 */ public static class Builder{ /** * 声明一个ExceptionMappingConfig实例 */ protected ExceptionMappingConfig target; /** * 根据现有的实例克隆一个target对象 * @param toClone */ public Builder(ExceptionMappingConfig toClone) { target = new ExceptionMappingConfig(toClone); } /** * 利用构造方法创建一个target对象 * @param name * @param exceptionClassName * @param result */ public Builder(String name, String exceptionClassName, String result) { target = new ExceptionMappingConfig(name, exceptionClassName, result); } /** * 设置名称 * @param name * @return */ public Builder name(String name) { target.name = name; return this; } /** * 设置异常类名称 * @param name * @return */ public Builder exceptionClassName(String name) { target.exceptionClassName = name; return this; } /** * 设置结果 * @param result * @return */ public Builder result(String result) { target.result = result; return this; } /** * 添加参数 * @param name * @param value * @return */ public Builder addParam(String name, String value) { target.params.put(name, value); return this; } /** * 添加一个map类型 * @param params * @return */ public Builder addParams(Map<String,String> params) { target.params.putAll(params); return this; } public Builder location(Location loc) { target.location = loc; return this; } /** * 创建该ExceptionMappingConfig对象 * @return */ public ExceptionMappingConfig build() { embalmTarget(); ExceptionMappingConfig result = target; target = new ExceptionMappingConfig(target); return result; } protected void embalmTarget() { target.params = Collections.unmodifiableMap(target.params); } } }
ResultTypeConfig(com.opensymphony.xwork2.config.entities)
/** * 返回结果类型的配置,在xml的配置文件中这相当于定义一个result-type类型 */ public class ResultTypeConfig extends Located implements Serializable { protected String className;//类名 protected String name;//类型名称 protected String defaultResultParam;//默认的结果参数 protected Map<String,String> params;//参数集 /** * 默认构造方法,在这里初始化该类的一些参数 * @param name * @param className */ protected ResultTypeConfig(String name, String className) { this.name = name; this.className = className; params = new LinkedHashMap<String,String>(); } /** * 根据现有的一个该类的实例克隆一个新的对象 * @param orig */ protected ResultTypeConfig(ResultTypeConfig orig) { this.name = orig.name; this.className = orig.className; this.defaultResultParam = orig.defaultResultParam; this.params = orig.params; } /** * 设置默认的结果参数 * @param defaultResultParam */ public void setDefaultResultParam(String defaultResultParam) { this.defaultResultParam = defaultResultParam; } /** * 获取默认的结果参数 * @return */ public String getDefaultResultParam() { return this.defaultResultParam; } /** * @deprecated Since 2.1, use {@link #getClassName()} instead */ @Deprecated public String getClazz() { return className; } public String getClassName() { return className; } public String getName() { return name; } public Map<String,String> getParams() { return this.params; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final ResultTypeConfig that = (ResultTypeConfig) o; if (className != null ? !className.equals(that.className) : that.className != null) return false; if (name != null ? !name.equals(that.name) : that.name != null) return false; if (params != null ? !params.equals(that.params) : that.params != null) return false; return true; } @Override public int hashCode() { int result; result = (className != null ? className.hashCode() : 0); result = 29 * result + (name != null ? name.hashCode() : 0); result = 29 * result + (params != null ? params.hashCode() : 0); return result; } /** * 这个类的builder方法。唯一创建该类的实例的方法。目的是为了维持执行对象的不变性。 * 该方式是通过结构化的方式来至此chain方式。设置完需要的参数之后,可以调用build方法创建一个实例 * 一下内部类的方法,通过名称即可了解该方法的具体作用 */ public static final class Builder { protected ResultTypeConfig target; public Builder(String name, String className) { target = new ResultTypeConfig(name, className); } public Builder(ResultTypeConfig orig) { target = new ResultTypeConfig(orig); } public Builder name(String name) { target.name = name; return this; } public Builder className(String name) { target.className = name; return this; } public Builder addParam(String name, String value) { target.params.put(name, value); return this; } public Builder addParams(Map<String,String> params) { target.params.putAll(params); return this; } public Builder defaultResultParam(String defaultResultParam) { target.defaultResultParam = defaultResultParam; return this; } public Builder location(Location loc) { target.location = loc; return this; } public ResultTypeConfig build() { embalmTarget(); ResultTypeConfig result = target; target = new ResultTypeConfig(target); return result; } protected void embalmTarget() { target.params = Collections.unmodifiableMap(target.params); } } }
ActionConfig(com.opensymphony.xwork2.config.entities)
/** * 包括所有需要被配置和一个可执行的action * <ul> * <li>方法名 - 这个方法名是将要被执行的action的方法。如果为空,这个Action将被关联到Action Interface并且执行execute()方法</li> * <li>类 - 这个Action的类名</li> * <li>参数 - 这些参数将被在action执行之前设置</li> * <li>结果 - 结果集 {String -> View class}</li> * <li>结果参数 - 返回结果的参数{String -> Map}</li> * <li>类型转换 - 用OGNL的类型转换为了使用getting/setting参数时</li> * </ul> */ public class ActionConfig extends Located implements Serializable { public static final String DEFAULT_METHOD = "execute";//默认执行的方法名 public static final String WILDCARD = "*";//通配符 protected List<InterceptorMapping> interceptors; // 一个InterceptorMapping的列表对象 protected Map<String,String> params;//参数 protected Map<String, ResultConfig> results;//结果集 protected List<ExceptionMappingConfig> exceptionMappings;//异常映射配置 protected String className;//类名 protected String methodName;//方法名 protected String packageName;//包名 protected String name;//名称 protected Set<String> allowedMethods; /** * 构造方法 * @param packageName * @param name * @param className */ protected ActionConfig(String packageName, String name, String className) { this.packageName = packageName; this.name = name; this.className = className; params = new LinkedHashMap<String, String>(); results = new LinkedHashMap<String, ResultConfig>(); interceptors = new ArrayList<InterceptorMapping>(); exceptionMappings = new ArrayList<ExceptionMappingConfig>(); allowedMethods = new HashSet<String>(); } /** * 负责一个ActionConfig对象 * @param orig The ActionConfig to clone * @Since 2.1 */ protected ActionConfig(ActionConfig orig) { this.name = orig.name; this.className = orig.className; this.methodName = orig.methodName; this.packageName = orig.packageName; this.params = new LinkedHashMap<String,String>(orig.params); this.interceptors = new ArrayList<InterceptorMapping>(orig.interceptors); this.results = new LinkedHashMap<String,ResultConfig>(orig.results); this.exceptionMappings = new ArrayList<ExceptionMappingConfig>(orig.exceptionMappings); this.allowedMethods = new HashSet<String>(orig.allowedMethods); } public String getName() { return name; } public String getClassName() { return className; } public List<ExceptionMappingConfig> getExceptionMappings() { return exceptionMappings; } public List<InterceptorMapping> getInterceptors() { return interceptors; } public Set<String> getAllowedMethods() { return allowedMethods; } /** * 返回类中方法的名字 * * @return name of the method to execute */ public String getMethodName() { return methodName; } /** * @return Returns the packageName. */ public String getPackageName() { return packageName; } public Map<String, String> getParams() { return params; } public Map<String, ResultConfig> getResults() { return results; } public boolean isAllowedMethod(String method) { if (allowedMethods.size() == 1 && WILDCARD.equals(allowedMethods.iterator().next())) { return true; } else { return method.equals(methodName != null ? methodName : DEFAULT_METHOD) || allowedMethods.contains(method); } } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof ActionConfig)) { return false; } final ActionConfig actionConfig = (ActionConfig) o; if ((className != null) ? (!className.equals(actionConfig.className)) : (actionConfig.className != null)) { return false; } if ((name != null) ? (!name.equals(actionConfig.name)) : (actionConfig.name != null)) { return false; } if ((interceptors != null) ? (!interceptors.equals(actionConfig.interceptors)) : (actionConfig.interceptors != null)) { return false; } if ((methodName != null) ? (!methodName.equals(actionConfig.methodName)) : (actionConfig.methodName != null)) { return false; } if ((params != null) ? (!params.equals(actionConfig.params)) : (actionConfig.params != null)) { return false; } if ((results != null) ? (!results.equals(actionConfig.results)) : (actionConfig.results != null)) { return false; } if ((allowedMethods != null) ? (!allowedMethods.equals(actionConfig.allowedMethods)) : (actionConfig.allowedMethods != null)) { return false; } return true; } @Override public int hashCode() { int result; result = (interceptors != null ? interceptors.hashCode() : 0); result = 31 * result + (params != null ? params.hashCode() : 0); result = 31 * result + (results != null ? results.hashCode() : 0); result = 31 * result + (exceptionMappings != null ? exceptionMappings.hashCode() : 0); result = 31 * result + (className != null ? className.hashCode() : 0); result = 31 * result + (methodName != null ? methodName.hashCode() : 0); result = 31 * result + (packageName != null ? packageName.hashCode() : 0); result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (allowedMethods != null ? allowedMethods.hashCode() : 0); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("{ActionConfig "); sb.append(name).append(" ("); sb.append(className); if (methodName != null) { sb.append(".").append(methodName).append("()"); } sb.append(")"); sb.append(" - ").append(location); sb.append("}"); return sb.toString(); } /** * 这个类的builder方法。唯一创建该类的实例的方法。目的是为了维持执行对象的不变性。 * 该方式是通过结构化的方式来至此chain方式。设置完需要的参数之后,可以调用build方法创建一个实例 */ public static class Builder implements InterceptorListHolder{ protected ActionConfig target; private boolean gotMethods; public Builder(ActionConfig toClone) { target = new ActionConfig(toClone); addAllowedMethod(toClone.getAllowedMethods()); } public Builder(String packageName, String name, String className) { target = new ActionConfig(packageName, name, className); } public Builder packageName(String name) { target.packageName = name; return this; } public Builder name(String name) { target.name = name; return this; } public Builder className(String name) { target.className = name; return this; } public Builder defaultClassName(String name) { if (StringUtils.isEmpty(target.className)) { target.className = name; } return this; } public Builder methodName(String method) { target.methodName = method; return this; } public Builder addExceptionMapping(ExceptionMappingConfig exceptionMapping) { target.exceptionMappings.add(exceptionMapping); return this; } public Builder addExceptionMappings(Collection<? extends ExceptionMappingConfig> mappings) { target.exceptionMappings.addAll(mappings); return this; } public Builder exceptionMappings(Collection<? extends ExceptionMappingConfig> mappings) { target.exceptionMappings.clear(); target.exceptionMappings.addAll(mappings); return this; } public Builder addInterceptor(InterceptorMapping interceptor) { target.interceptors.add(interceptor); return this; } public Builder addInterceptors(List<InterceptorMapping> interceptors) { target.interceptors.addAll(interceptors); return this; } public Builder interceptors(List<InterceptorMapping> interceptors) { target.interceptors.clear(); target.interceptors.addAll(interceptors); return this; } public Builder addParam(String name, String value) { target.params.put(name, value); return this; } public Builder addParams(Map<String,String> params) { target.params.putAll(params); return this; } public Builder addResultConfig(ResultConfig resultConfig) { target.results.put(resultConfig.getName(), resultConfig); return this; } public Builder addResultConfigs(Collection<ResultConfig> configs) { for (ResultConfig rc : configs) { target.results.put(rc.getName(), rc); } return this; } public Builder addResultConfigs(Map<String,ResultConfig> configs) { target.results.putAll(configs); return this; } public Builder addAllowedMethod(String methodName) { target.allowedMethods.add(methodName); return this; } public Builder addAllowedMethod(Collection<String> methods) { if (methods != null) { gotMethods = true; target.allowedMethods.addAll(methods); } return this; } public Builder location(Location loc) { target.location = loc; return this; } public ActionConfig build() { embalmTarget(); ActionConfig result = target; target = new ActionConfig(target); return result; } protected void embalmTarget() { if (!gotMethods && target.allowedMethods.isEmpty()) { target.allowedMethods.add(WILDCARD); } target.params = Collections.unmodifiableMap(target.params); target.results = Collections.unmodifiableMap(target.results); target.interceptors = Collections.unmodifiableList(target.interceptors); target.exceptionMappings = Collections.unmodifiableList(target.exceptionMappings); target.allowedMethods = Collections.unmodifiableSet(target.allowedMethods); } } }
PackageConfig(com.opensymphony.xwork2.config.entities)
/** * package的配置,在xml配置文件中,对应package标签 */ public class PackageConfig extends Located implements Comparable, Serializable, InterceptorLocator { private static final Logger LOG = LoggerFactory.getLogger(PackageConfig.class); protected Map<String, ActionConfig> actionConfigs;//定义一个ActionConfig的Map列表(相当于xml配置文件中的action) protected Map<String, ResultConfig> globalResultConfigs;//定义全局结果映射配置 protected Map<String, Object> interceptorConfigs;//定义拦截器名字和类的映射关系 protected Map<String, ResultTypeConfig> resultTypeConfigs;//返回类型的配置 protected List<ExceptionMappingConfig> globalExceptionMappingConfigs;//全集异常映射配置 protected List<PackageConfig> parents;//父package protected String defaultInterceptorRef;//默认拦截器 protected String defaultActionRef;//默认Action-ref protected String defaultResultType;//默认返回结果类型 protected String defaultClassRef; protected String name;//package名称 protected String namespace = "";//namespace protected boolean isAbstract = false; protected boolean needsRefresh; /** * 初始化所有参数 * @param name */ protected PackageConfig(String name) { this.name = name; actionConfigs = new LinkedHashMap<String, ActionConfig>(); globalResultConfigs = new LinkedHashMap<String, ResultConfig>(); interceptorConfigs = new LinkedHashMap<String, Object>(); resultTypeConfigs = new LinkedHashMap<String, ResultTypeConfig>(); globalExceptionMappingConfigs = new ArrayList<ExceptionMappingConfig>(); parents = new ArrayList<PackageConfig>(); } /** * 通过现有的PackageConfig初始化所有的参数信息 * @param orig */ protected PackageConfig(PackageConfig orig) { this.defaultInterceptorRef = orig.defaultInterceptorRef; this.defaultActionRef = orig.defaultActionRef; this.defaultResultType = orig.defaultResultType; this.defaultClassRef = orig.defaultClassRef; this.name = orig.name; this.namespace = orig.namespace; this.isAbstract = orig.isAbstract; this.needsRefresh = orig.needsRefresh; this.actionConfigs = new LinkedHashMap<String, ActionConfig>(orig.actionConfigs); this.globalResultConfigs = new LinkedHashMap<String, ResultConfig>(orig.globalResultConfigs); this.interceptorConfigs = new LinkedHashMap<String, Object>(orig.interceptorConfigs); this.resultTypeConfigs = new LinkedHashMap<String, ResultTypeConfig>(orig.resultTypeConfigs); this.globalExceptionMappingConfigs = new ArrayList<ExceptionMappingConfig>(orig.globalExceptionMappingConfigs); this.parents = new ArrayList<PackageConfig>(orig.parents); } /** * 返回是否是抽象的 * @return */ public boolean isAbstract() { return isAbstract; } /** * 返回actionConfigs * @return */ public Map<String, ActionConfig> getActionConfigs() { return actionConfigs; } /** * 返回当前package中所有可用的ActionConfigs映射,在父类packages中定义的ActionConfigs将被包含在这个Map里面 * @return 一个以action作为名词的ActionConfig对象的Map * @see ActionConfig */ public Map<String, ActionConfig> getAllActionConfigs() { Map<String, ActionConfig> retMap = new LinkedHashMap<String, ActionConfig>(); if (!parents.isEmpty()) { for (PackageConfig parent : parents) { retMap.putAll(parent.getAllActionConfigs()); } } retMap.putAll(getActionConfigs()); return retMap; } /** * returns the Map of all the global ResultConfigs available in the current package. * Global ResultConfigs defined in ancestor packages will be included in this Map. * * @return a Map of Result Objects with the result name as the key * @see ResultConfig */ public Map<String, ResultConfig> getAllGlobalResults() { Map<String, ResultConfig> retMap = new LinkedHashMap<String, ResultConfig>(); if (!parents.isEmpty()) { for (PackageConfig parentConfig : parents) { retMap.putAll(parentConfig.getAllGlobalResults()); } } retMap.putAll(getGlobalResultConfigs()); return retMap; } /** * returns the Map of all InterceptorConfigs and InterceptorStackConfigs available in the current package. * InterceptorConfigs defined in ancestor packages will be included in this Map. * * @return a Map of InterceptorConfig and InterceptorStackConfig Objects with the ref-name as the key * @see InterceptorConfig * @see InterceptorStackConfig */ public Map<String, Object> getAllInterceptorConfigs() { Map<String, Object> retMap = new LinkedHashMap<String, Object>(); if (!parents.isEmpty()) { for (PackageConfig parentContext : parents) { retMap.putAll(parentContext.getAllInterceptorConfigs()); } } retMap.putAll(getInterceptorConfigs()); return retMap; } /** * returns the Map of all the ResultTypeConfigs available in the current package. * ResultTypeConfigs defined in ancestor packages will be included in this Map. * * @return a Map of ResultTypeConfig Objects with the result type name as the key * @see ResultTypeConfig */ public Map<String, ResultTypeConfig> getAllResultTypeConfigs() { Map<String, ResultTypeConfig> retMap = new LinkedHashMap<String, ResultTypeConfig>(); if (!parents.isEmpty()) { for (PackageConfig parentContext : parents) { retMap.putAll(parentContext.getAllResultTypeConfigs()); } } retMap.putAll(getResultTypeConfigs()); return retMap; } /** * returns the List of all the ExceptionMappingConfigs available in the current package. * ExceptionMappingConfigs defined in ancestor packages will be included in this list. * * @return a List of ExceptionMappingConfigs Objects with the result type name as the key * @see ExceptionMappingConfig */ public List<ExceptionMappingConfig> getAllExceptionMappingConfigs() { List<ExceptionMappingConfig> allExceptionMappings = new ArrayList<ExceptionMappingConfig>(); if (!parents.isEmpty()) { for (PackageConfig parentContext : parents) { allExceptionMappings.addAll(parentContext.getAllExceptionMappingConfigs()); } } allExceptionMappings.addAll(getGlobalExceptionMappingConfigs()); return allExceptionMappings; } public String getDefaultInterceptorRef() { return defaultInterceptorRef; } public String getDefaultActionRef() { return defaultActionRef; } public String getDefaultClassRef() { if ((defaultClassRef == null) && !parents.isEmpty()) { for (PackageConfig parent : parents) { String parentDefault = parent.getDefaultClassRef(); if (parentDefault != null) { return parentDefault; } } } return defaultClassRef; } /** * Returns the default result type for this package. */ public String getDefaultResultType() { return defaultResultType; } /** * gets the default interceptor-ref name. If this is not set on this PackageConfig, it searches the parent * PackageConfigs in order until it finds one. */ public String getFullDefaultInterceptorRef() { if ((defaultInterceptorRef == null) && !parents.isEmpty()) { for (PackageConfig parent : parents) { String parentDefault = parent.getFullDefaultInterceptorRef(); if (parentDefault != null) { return parentDefault; } } } return defaultInterceptorRef; } /** * gets the default action-ref name. If this is not set on this PackageConfig, it searches the parent * PackageConfigs in order until it finds one. */ public String getFullDefaultActionRef() { if ((defaultActionRef == null) && !parents.isEmpty()) { for (PackageConfig parent : parents) { String parentDefault = parent.getFullDefaultActionRef(); if (parentDefault != null) { return parentDefault; } } } return defaultActionRef; } /** * 返回该package的默认的result type * 如果该package没有默认的result tyoe,但是它有父package,我们将尝试寻找该package的父package的默认result type */ public String getFullDefaultResultType() { if ((defaultResultType == null) && !parents.isEmpty()) { for (PackageConfig parent : parents) { String parentDefault = parent.getFullDefaultResultType(); if (parentDefault != null) { return parentDefault; } } } return defaultResultType; } /** * gets the global ResultConfigs local to this package * * @return a Map of ResultConfig objects keyed by result name * @see ResultConfig */ public Map<String, ResultConfig> getGlobalResultConfigs() { return globalResultConfigs; } /** * gets the InterceptorConfigs and InterceptorStackConfigs local to this package * * @return a Map of InterceptorConfig and InterceptorStackConfig objects keyed by ref-name * @see InterceptorConfig * @see InterceptorStackConfig */ public Map<String, Object> getInterceptorConfigs() { return interceptorConfigs; } public String getName() { return name; } public String getNamespace() { return namespace; } public List<PackageConfig> getParents() { return new ArrayList<PackageConfig>(parents); } /** * gets the ResultTypeConfigs local to this package * * @return a Map of ResultTypeConfig objects keyed by result name * @see ResultTypeConfig */ public Map<String, ResultTypeConfig> getResultTypeConfigs() { return resultTypeConfigs; } public boolean isNeedsRefresh() { return needsRefresh; } /** * gets the ExceptionMappingConfigs local to this package * * @return a Map of ExceptionMappingConfig objects keyed by result name * @see ExceptionMappingConfig */ public List<ExceptionMappingConfig> getGlobalExceptionMappingConfigs() { return globalExceptionMappingConfigs; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof PackageConfig)) { return false; } final PackageConfig packageConfig = (PackageConfig) o; if (isAbstract != packageConfig.isAbstract) { return false; } if ((actionConfigs != null) ? (!actionConfigs.equals(packageConfig.actionConfigs)) : (packageConfig.actionConfigs != null)) { return false; } if ((defaultResultType != null) ? (!defaultResultType.equals(packageConfig.defaultResultType)) : (packageConfig.defaultResultType != null)) { return false; } if ((defaultClassRef != null) ? (!defaultClassRef.equals(packageConfig.defaultClassRef)) : (packageConfig.defaultClassRef != null)) { return false; } if ((globalResultConfigs != null) ? (!globalResultConfigs.equals(packageConfig.globalResultConfigs)) : (packageConfig.globalResultConfigs != null)) { return false; } if ((interceptorConfigs != null) ? (!interceptorConfigs.equals(packageConfig.interceptorConfigs)) : (packageConfig.interceptorConfigs != null)) { return false; } if ((name != null) ? (!name.equals(packageConfig.name)) : (packageConfig.name != null)) { return false; } if ((namespace != null) ? (!namespace.equals(packageConfig.namespace)) : (packageConfig.namespace != null)) { return false; } if ((parents != null) ? (!parents.equals(packageConfig.parents)) : (packageConfig.parents != null)) { return false; } if ((resultTypeConfigs != null) ? (!resultTypeConfigs.equals(packageConfig.resultTypeConfigs)) : (packageConfig.resultTypeConfigs != null)) { return false; } if ((globalExceptionMappingConfigs != null) ? (!globalExceptionMappingConfigs.equals(packageConfig.globalExceptionMappingConfigs)) : (packageConfig.globalExceptionMappingConfigs != null)) { return false; } return true; } @Override public int hashCode() { int result; result = ((name != null) ? name.hashCode() : 0); result = (29 * result) + ((parents != null) ? parents.hashCode() : 0); result = (29 * result) + ((actionConfigs != null) ? actionConfigs.hashCode() : 0); result = (29 * result) + ((globalResultConfigs != null) ? globalResultConfigs.hashCode() : 0); result = (29 * result) + ((interceptorConfigs != null) ? interceptorConfigs.hashCode() : 0); result = (29 * result) + ((resultTypeConfigs != null) ? resultTypeConfigs.hashCode() : 0); result = (29 * result) + ((globalExceptionMappingConfigs != null) ? globalExceptionMappingConfigs.hashCode() : 0); result = (29 * result) + ((defaultResultType != null) ? defaultResultType.hashCode() : 0); result = (29 * result) + ((defaultClassRef != null) ? defaultClassRef.hashCode() : 0); result = (29 * result) + ((namespace != null) ? namespace.hashCode() : 0); result = (29 * result) + (isAbstract ? 1 : 0); return result; } @Override public String toString() { return "{PackageConfig Name:" + name + " namespace:" + namespace + " parents:" + parents + "}"; } public int compareTo(Object o) { PackageConfig other = (PackageConfig) o; String full = namespace + "!" + name; String otherFull = other.namespace + "!" + other.name; // note, this isn't perfect (could come from different parents), but it is "good enough" return full.compareTo(otherFull); } public Object getInterceptorConfig(String name) { return getAllInterceptorConfigs().get(name); } /** * 这个类的构建类。该实例是唯一创建该对象实例的方法。目的是执行对象的不变性。这个方法将被用来支持链式创建。 * 当设置完了你需要设置的参数之后,通过调用build()方法,就可以常见该对象 */ public static class Builder implements InterceptorLocator { //该对象的一个实例 protected PackageConfig target; private boolean strictDMI; /** * 设置package的名称 * @param name */ public Builder(String name) { target = new PackageConfig(name); } /** * 通过复制config创建一个新的PackageConfig对象 * @param config */ public Builder(PackageConfig config) { target = new PackageConfig(config); } /** * 设置target对象的名称 * @param name * @return */ public Builder name(String name) { target.name = name; return this; } /** * 设置target对象的isabstract属性 * @param isAbstract * @return */ public Builder isAbstract(boolean isAbstract) { target.isAbstract = isAbstract; return this; } /** * 设置对象的defaultInterceptorRef属性 * @param name * @return */ public Builder defaultInterceptorRef(String name) { target.defaultInterceptorRef = name; return this; } /** * 设置对象的defaultActionRef属性 * @param name * @return */ public Builder defaultActionRef(String name) { target.defaultActionRef = name; return this; } /** * 设置对象的defaultClassRef属性 * @param defaultClassRef * @return */ public Builder defaultClassRef(String defaultClassRef) { target.defaultClassRef = defaultClassRef; return this; } /** * 为这个Package设置默认的结果类型 * * @param defaultResultType */ public Builder defaultResultType(String defaultResultType) { target.defaultResultType = defaultResultType; return this; } /** * 为当前target设置namespace属性 * @param namespace * @return */ public Builder namespace(String namespace) { if (namespace == null) { target.namespace = ""; } else { target.namespace = namespace; } return this; } public Builder needsRefresh(boolean needsRefresh) { target.needsRefresh = needsRefresh; return this; } public Builder addActionConfig(String name, ActionConfig action) { target.actionConfigs.put(name, action); return this; } public Builder addParents(List<PackageConfig> parents) { for (PackageConfig config : parents) { addParent(config); } return this; } public Builder addGlobalResultConfig(ResultConfig resultConfig) { target.globalResultConfigs.put(resultConfig.getName(), resultConfig); return this; } public Builder addGlobalResultConfigs(Map<String, ResultConfig> resultConfigs) { target.globalResultConfigs.putAll(resultConfigs); return this; } public Builder addExceptionMappingConfig(ExceptionMappingConfig exceptionMappingConfig) { target.globalExceptionMappingConfigs.add(exceptionMappingConfig); return this; } public Builder addGlobalExceptionMappingConfigs(List<ExceptionMappingConfig> exceptionMappingConfigs) { target.globalExceptionMappingConfigs.addAll(exceptionMappingConfigs); return this; } public Builder addInterceptorConfig(InterceptorConfig config) { target.interceptorConfigs.put(config.getName(), config); return this; } public Builder addInterceptorStackConfig(InterceptorStackConfig config) { target.interceptorConfigs.put(config.getName(), config); return this; } public Builder addParent(PackageConfig parent) { target.parents.add(0, parent); return this; } public Builder addResultTypeConfig(ResultTypeConfig config) { target.resultTypeConfigs.put(config.getName(), config); return this; } public Builder location(Location loc) { target.location = loc; return this; } public boolean isNeedsRefresh() { return target.needsRefresh; } public String getDefaultClassRef() { return target.defaultClassRef; } public String getName() { return target.name; } public String getNamespace() { return target.namespace; } /** * 返回该package的默认的result type * @return */ public String getFullDefaultResultType() { return target.getFullDefaultResultType(); } public ResultTypeConfig getResultType(String type) { return target.getAllResultTypeConfigs().get(type); } public Object getInterceptorConfig(String name) { return target.getAllInterceptorConfigs().get(name); } public Builder strictMethodInvocation(boolean strict) { strictDMI = strict; return this; } public boolean isStrictMethodInvocation() { return strictDMI; } public PackageConfig build() { embalmTarget(); PackageConfig result = target; target = new PackageConfig(result); return result; } protected void embalmTarget() { target.actionConfigs = Collections.unmodifiableMap(target.actionConfigs); target.globalResultConfigs = Collections.unmodifiableMap(target.globalResultConfigs); target.interceptorConfigs = Collections.unmodifiableMap(target.interceptorConfigs); target.resultTypeConfigs = Collections.unmodifiableMap(target.resultTypeConfigs); target.globalExceptionMappingConfigs = Collections.unmodifiableList(target.globalExceptionMappingConfigs); target.parents = Collections.unmodifiableList(target.parents); } @Override public String toString() { return "[BUILDER] " + target.toString(); } } }
这个方法中所需的类基本介绍完了,下面介绍解析过程;在此调用XmlConfigurationProvider类的addPackage(Element packageElement)方法,该方法具体内容如下:
/** * 创建一个XML元素代表一个packageconfig。 */ protected PackageConfig addPackage(Element packageElement) throws ConfigurationException { //创建一个PackageConfig的内部类Builder PackageConfig.Builder newPackage = buildPackageContext(packageElement);//用该类创建一个package对象 if (newPackage.isNeedsRefresh()) { return newPackage.build(); } if (LOG.isDebugEnabled()) { LOG.debug("Loaded " + newPackage); } //为这个package添加result types 和默认的result addResultTypes(newPackage, packageElement); //为这个package添加interceptors和interceptor stacks loadInterceptors(newPackage, packageElement); //为这个package添加默认的interceptors loadDefaultInterceptorRef(newPackage, packageElement); //为这个package添加默认的default-class-ref loadDefaultClassRef(newPackage, packageElement); //为package添加全局results loadGlobalResults(newPackage, packageElement); //为这个package添加全局的exception loadGobalExceptionMappings(newPackage, packageElement); //获取action元素 NodeList actionList = packageElement.getElementsByTagName("action"); //遍历action元素 for (int i = 0; i < actionList.getLength(); i++) { Element actionElement = (Element) actionList.item(i);//获取第i个action元素 //把该action元素添加到package中 addAction(actionElement, newPackage); } // load the default action reference for this package //为该package加载默认的action loadDefaultActionRef(newPackage, packageElement); //实例化一个PackageConfig对象 PackageConfig cfg = newPackage.build(); //把该对象添加到configuration(DefaultConfiguration)的packageContexts中 configuration.addPackageConfig(cfg.getName(), cfg); //返回该cfg对象 return cfg; }
在这里对其具体代码进行分析:
//为这个package添加result types 和默认的result
addResultTypes(newPackage, packageElement);该方法的具体代码如下:
/** * 为这个package添加result types 和默认的result * @param packageContext * @param element */ protected void addResultTypes(PackageConfig.Builder packageContext, Element element) { NodeList resultTypeList = element.getElementsByTagName("result-type");//以getElementsByTagName的形式获取所有的("result-type") /** * 对result-type进行遍历 */ for (int i = 0; i < resultTypeList.getLength(); i++) { Element resultTypeElement = (Element) resultTypeList.item(i);//获取第I个node对象 String name = resultTypeElement.getAttribute("name");//获取该元素的name属性 String className = resultTypeElement.getAttribute("class");//获取该元素的class属性 String def = resultTypeElement.getAttribute("default");//获取该元素的defaul属性 /** * 获取该元素的location */ Location loc = DomHelper.getLocationObject(resultTypeElement); //获取指定类名的类 Class clazz = verifyResultType(className, loc); if (clazz != null) { String paramName = null; try { paramName = (String) clazz.getField("DEFAULT_PARAM").get(null); } catch (Throwable t) { // if we get here, the result type doesn't have a default param defined. } /** * 创建一个ResultTypeConfig对象 */ ResultTypeConfig.Builder resultType = new ResultTypeConfig.Builder(name, className).defaultResultParam(paramName) .location(DomHelper.getLocationObject(resultTypeElement)); Map<String, String> params = XmlHelper.getParams(resultTypeElement); if (!params.isEmpty()) { resultType.addParams(params); } packageContext.addResultTypeConfig(resultType.build()); // 设置默认的结果类型 if ("true".equals(def)) { packageContext.defaultResultType(name); } } } }
//为这个package添加interceptors和interceptor stacks
loadInterceptors(newPackage, packageElement);该方法具体内容如下:
/** * 为这个package添加interceptors和interceptor stacks * @param context * @param element * @throws ConfigurationException */ protected void loadInterceptors(PackageConfig.Builder context, Element element) throws ConfigurationException { NodeList interceptorList = element.getElementsByTagName("interceptor");//获取所有的interceptor配置 //对获取到的interceptor列表进行遍历 for (int i = 0; i < interceptorList.getLength(); i++) { Element interceptorElement = (Element) interceptorList.item(i);//获取第i个元素 String name = interceptorElement.getAttribute("name");//获取元素的name String className = interceptorElement.getAttribute("class");//获取元素的class Map<String, String> params = XmlHelper.getParams(interceptorElement); /** * 创建一个InterceptorConfig对象 */ InterceptorConfig config = new InterceptorConfig.Builder(name, className) .addParams(params) .location(DomHelper.getLocationObject(interceptorElement)) .build(); //把创建的InterceptorConfig对象放入PackageConfig中 context.addInterceptorConfig(config); } /** * 加载InterceptorStack */ loadInterceptorStacks(element, context); }
在该方法中又调用了设置InterceptorStacks的方法,该方法具体如下:
/** * 为package加载InterceptorStack * @param element * @param context * @throws ConfigurationException */ protected void loadInterceptorStacks(Element element, PackageConfig.Builder context) throws ConfigurationException { NodeList interceptorStackList = element.getElementsByTagName("interceptor-stack");//获取名字为interceptor-stack的节点 /** * 对节点进行遍历 */ for (int i = 0; i < interceptorStackList.getLength(); i++) { Element interceptorStackElement = (Element) interceptorStackList.item(i);//获取第I个节点 InterceptorStackConfig config = loadInterceptorStack(interceptorStackElement, context); context.addInterceptorStackConfig(config); } }
在该方法内部调用了loadInterceptorStack方法,该方法具体如下:
/** * 加载InterceptorStack */ protected InterceptorStackConfig loadInterceptorStack(Element element, PackageConfig.Builder context) throws ConfigurationException { String name = element.getAttribute("name");//得到节点的名字 InterceptorStackConfig.Builder config = new InterceptorStackConfig.Builder(name) .location(DomHelper.getLocationObject(element));//创建一个InterceptorStackConfig对象 NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref");//查找所有的interceptor-ref的节点 /** * 对查找到的Node进行遍历 */ for (int j = 0; j < interceptorRefList.getLength(); j++) { Element interceptorRefElement = (Element) interceptorRefList.item(j);//获取第J个节点 List<InterceptorMapping> interceptors = lookupInterceptorReference(context, interceptorRefElement); config.addInterceptors(interceptors); } return config.build(); }
在该方法内部调用lookupInterceptorReference方法,该方法具体内容如下:
/** * 从interceptor-ref的名字查找Interceptor类并创建一个实例,并添加到provided List中,或, * 如果这个ref是一个stack,它将会把这个Interceptor实例从List中添加到一个stack中 * @param interceptorRefElement Element to pull interceptor ref data from * @param context The PackageConfig to lookup the interceptor from * @return A list of Interceptor objects */ private List<InterceptorMapping> lookupInterceptorReference(PackageConfig.Builder context, Element interceptorRefElement) throws ConfigurationException { String refName = interceptorRefElement.getAttribute("name");//获取节点的名称 Map<String, String> refParams = XmlHelper.getParams(interceptorRefElement); Location loc = LocationUtils.getLocation(interceptorRefElement); return InterceptorBuilder.constructInterceptorReference(context, refName, refParams, loc, objectFactory); }
至此该package的InterceptorStack加载完成
//为这个package添加默认的interceptors
loadDefaultInterceptorRef(newPackage, packageElement);
/** * 加载默认的defaul interceptor * @param packageContext * @param element */ protected void loadDefaultInterceptorRef(PackageConfig.Builder packageContext, Element element) { NodeList resultTypeList = element.getElementsByTagName("default-interceptor-ref");//获取package下面的所有的default-interceptor-ref元素 /** * 若default-interceptor-ref元素多于0个 */ if (resultTypeList.getLength() > 0) { //获取第一个default-interceptor节点 Element defaultRefElement = (Element) resultTypeList.item(0); packageContext.defaultInterceptorRef(defaultRefElement.getAttribute("name"));//把default-interceptor-ref的名字添加到package中 } }
//为这个package添加默认的default-class-ref
loadDefaultClassRef(newPackage, packageElement);
/** * 加载默认的default-class-ref标签 * @param packageContext * @param element */ protected void loadDefaultClassRef(PackageConfig.Builder packageContext, Element element) { NodeList defaultClassRefList = element.getElementsByTagName("default-class-ref");//获取所有的default-class-ref节点 //如果在配置文件中节点名的节点大于0 if (defaultClassRefList.getLength() > 0) { Element defaultClassRefElement = (Element) defaultClassRefList.item(0);//获取第一个节点 packageContext.defaultClassRef(defaultClassRefElement.getAttribute("class"));//放入package的defaultClassRef中 } }
//为package添加全局results
loadGlobalResults(newPackage, packageElement);
/** * 为package添加全局results */ protected void loadGlobalResults(PackageConfig.Builder packageContext, Element packageElement) { NodeList globalResultList = packageElement.getElementsByTagName("global-results");//查询所有的global-results //如果在配置文件中节点名的节点大于0 if (globalResultList.getLength() > 0) { Element globalResultElement = (Element) globalResultList.item(0);//获取该节点的第0个节点 Map<String, ResultConfig> results = buildResults(globalResultElement, packageContext);//创建一个全局result到包的映射关系 packageContext.addGlobalResultConfigs(results); } }
//为这个package添加全局的exception
loadGobalExceptionMappings(newPackage, packageElement);
/** * 从xml的元素中添加全局的结果Exception */ protected void loadGobalExceptionMappings(PackageConfig.Builder packageContext, Element packageElement) { NodeList globalExceptionMappingList = packageElement.getElementsByTagName("global-exception-mappings");//查找所有的global-exception-mappings //如果节点中global-exception-mappings的个数大于0 if (globalExceptionMappingList.getLength() > 0) { Element globalExceptionMappingElement = (Element) globalExceptionMappingList.item(0);//获取第一个global-exception-mapping节点 List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(globalExceptionMappingElement, packageContext); packageContext.addGlobalExceptionMappingConfigs(exceptionMappings);//为package添加全局异常映射关系 } }
NodeList actionList = packageElement.getElementsByTagName("action");//查找所有的action节点
//把该action元素添加到package中
addAction(actionElement, newPackage);
/** * 把Action放入package中 * @param actionElement action节点 * @param packageContext package上下文 * @throws ConfigurationException 异常信息 */ protected void addAction(Element actionElement, PackageConfig.Builder packageContext) throws ConfigurationException { String name = actionElement.getAttribute("name");//获取action的名称 String className = actionElement.getAttribute("class");//获取节点的class String methodName = actionElement.getAttribute("method");//获取节点的method Location location = DomHelper.getLocationObject(actionElement);//获取该节点的location //判断location是否为空 if (location == null) { if (LOG.isWarnEnabled()) { LOG.warn("location null for " + className); } } //如果methodName为空,则设置其为null methodName = (methodName.trim().length() > 0) ? methodName.trim() : null; // if there isnt a class name specified for an <action/> then try to // use the default-class-ref from the <package/> //该部分代码已注释 if (StringUtils.isEmpty(className)) { // if there is a package default-class-ref use that, otherwise use action support /* if (StringUtils.isNotEmpty(packageContext.getDefaultClassRef())) { className = packageContext.getDefaultClassRef(); } else { className = ActionSupport.class.getName(); }*/ } else { if (!verifyAction(className, name, location)) { if (LOG.isErrorEnabled()) LOG.error("Unable to verify action [#0] with class [#1], from [#2]", name, className, location.toString()); return; } } //配置result Map<String, ResultConfig> results; try { //创建一个ResultConfig对象的map从给定的xml元素 results = buildResults(actionElement, packageContext); } catch (ConfigurationException e) { throw new ConfigurationException("Error building results for action " + name + " in namespace " + packageContext.getNamespace(), e, actionElement); } //获取该action的拦截器 List<InterceptorMapping> interceptorList = buildInterceptorList(actionElement, packageContext); //获取该action的异常映射 List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(actionElement, packageContext); //获取该action的allowed-method属性集合 Set<String> allowedMethods = buildAllowedMethods(actionElement, packageContext); //根据解析出来的数据创建一个ActionConfig对象 ActionConfig actionConfig = new ActionConfig.Builder(packageContext.getName(), name, className) .methodName(methodName) .addResultConfigs(results) .addInterceptors(interceptorList) .addExceptionMappings(exceptionMappings) .addParams(XmlHelper.getParams(actionElement)) .addAllowedMethod(allowedMethods) .location(location) .build(); //把新建的actionconfig放入packageContext中 packageContext.addActionConfig(name, actionConfig); if (LOG.isDebugEnabled()) { LOG.debug("Loaded " + (StringUtils.isNotEmpty(packageContext.getNamespace()) ? (packageContext.getNamespace() + "/") : "") + name + " in '" + packageContext.getName() + "' package:" + actionConfig); } }
在这个方法内部调用了buildResult(Element element, PackageConfig.Builder packageContext)方法,该方法具体如下:
/** * 创建一个ResultConfig对象的map从给定的xml元素 */ protected Map<String, ResultConfig> buildResults(Element element, PackageConfig.Builder packageContext) { NodeList resultEls = element.getElementsByTagName("result");//获取节点的所有result节点 Map<String, ResultConfig> results = new LinkedHashMap<String, ResultConfig>();//创建一个result的map /** * 遍历result节点 */ for (int i = 0; i < resultEls.getLength(); i++) { Element resultElement = (Element) resultEls.item(i);//获取第i个节点 /** * 如果该节点的父节点为给定的global-results节点,或该节点的父节点的名字等于给定的global-results节点的名字相等 */ if (resultElement.getParentNode().equals(element) || resultElement.getParentNode().getNodeName().equals(element.getNodeName())) { String resultName = resultElement.getAttribute("name");//获取该节点的name属性 String resultType = resultElement.getAttribute("type");//获取该节点的type属性 //如果未设置该节点的name属性,则默认为SUCCESS if (StringUtils.isEmpty(resultName)) { resultName = Action.SUCCESS; } //如果未设置该节点的type属性,我们将继承该节点的父package的类型 if (StringUtils.isEmpty(resultType)) { //得到该节点父节点的默认result type resultType = packageContext.getFullDefaultResultType(); //监测当前的resulttype是否有值 if (StringUtils.isEmpty(resultType)) { //如果没值,则抛出异常 throw new ConfigurationException("No result type specified for result named '" + resultName + "', perhaps the parent package does not specify the result type?", resultElement); } } /** * 获取该package中的resultType */ ResultTypeConfig config = packageContext.getResultType(resultType); if (config == null) { throw new ConfigurationException("There is no result type defined for type '" + resultType + "' mapped with name '" + resultName + "'." + " Did you mean '" + guessResultType(resultType) + "'?", resultElement); } //获取ResultTypeConfig的类 String resultClass = config.getClazz(); //无效的结果类型定义的结果 if (resultClass == null) { throw new ConfigurationException("Result type '" + resultType + "' is invalid"); } /** * 获取该resultElement的一个resultParams的Map */ Map<String, String> resultParams = XmlHelper.getParams(resultElement); if (resultParams.size() == 0) //或许,这里之后一个默认的参数 { //如果<result ...>something</result>让后我们将添加一个'something'的 属性作为经常用到的属性 if (resultElement.getChildNodes().getLength() >= 1) { //新建一个LinkedHashMap resultParams = new LinkedHashMap<String, String>(); String paramName = config.getDefaultResultParam();//获取默认的result参数 //如果默认参数不为空 if (paramName != null) { StringBuilder paramValue = new StringBuilder();//创建一个StringBuilder对象 //遍历resultElement的子节点 for (int j = 0; j < resultElement.getChildNodes().getLength(); j++) { //如果该节点的节点类型是TEXT_NODE的话 if (resultElement.getChildNodes().item(j).getNodeType() == Node.TEXT_NODE) { String val = resultElement.getChildNodes().item(j).getNodeValue();//获取节点值 //如果节点值不为空,则把其添加到paramValue中 if (val != null) { paramValue.append(val); } } } String val = paramValue.toString().trim();//去掉空格 //如果其不为空,则把结果放入resultParams中 if (val.length() > 0) { resultParams.put(paramName, val); } } else { if (LOG.isWarnEnabled()) { LOG.warn("no default parameter defined for result of type " + config.getName()); } } } } //创建一个新的参数map,如此一来,这些结果参数能覆盖配置参数 Map<String, String> params = new LinkedHashMap<String, String>(); Map<String, String> configParams = config.getParams();//获取ResultTypeConfig中的配置参数 //如果配置参数不为空,则把其放入新建立的params的MAP中 if (configParams != null) { params.putAll(configParams); } //把resultParams放入params中 params.putAll(resultParams); /** * 创建一个新的resultConfig */ ResultConfig resultConfig = new ResultConfig.Builder(resultName, resultClass) .addParams(params) .location(DomHelper.getLocationObject(element)) .build(); //把resultConfig放入result中 results.put(resultConfig.getName(), resultConfig); } } //返回result return results; }
为该action添加拦截器
/** * 添加拦截器 * @param element 元素 * @param context package上下文 * @return * @throws ConfigurationException */ protected List<InterceptorMapping> buildInterceptorList(Element element, PackageConfig.Builder context) throws ConfigurationException { List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>();//创建一个拦截器Map List NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref");//获取所有的interceptor-ref //对interceptor-ref进行遍历 for (int i = 0; i < interceptorRefList.getLength(); i++) { Element interceptorRefElement = (Element) interceptorRefList.item(i);//获取第I个interceptor-ref节点 //如果该节点的父节点是action if (interceptorRefElement.getParentNode().equals(element) || interceptorRefElement.getParentNode().getNodeName().equals(element.getNodeName())) { //在全局拦截器中进行查找 List<InterceptorMapping> interceptors = lookupInterceptorReference(context, interceptorRefElement); interceptorList.addAll(interceptors); } } //返回一个拦截器列表 return interceptorList; }
为该action添加异常映射
/** * 通过给定的xml节点创建一个ExceptionMapping(ResultConfig) * @param element 节点 * @param packageContext 包 */ protected List<ExceptionMappingConfig> buildExceptionMappings(Element element, PackageConfig.Builder packageContext) { NodeList exceptionMappingEls = element.getElementsByTagName("exception-mapping");//获取exception-mapping元素节点 List<ExceptionMappingConfig> exceptionMappings = new ArrayList<ExceptionMappingConfig>();//创建一个异常映射list列表 /** * 遍历exception-mapping元素节点 */ for (int i = 0; i < exceptionMappingEls.getLength(); i++) { Element ehElement = (Element) exceptionMappingEls.item(i);//获取第I个exception-mapping元素节点 //如果该节点的父节点为给定的global-exception-mappings,则运行 if (ehElement.getParentNode().equals(element) || ehElement.getParentNode().getNodeName().equals(element.getNodeName())) { String emName = ehElement.getAttribute("name");//获取节点元素的name属性 String exceptionClassName = ehElement.getAttribute("exception");//获取节点元素的exception属性 String exceptionResult = ehElement.getAttribute("result");//获取接电源是的result属性 /** * 把该节点组装成一个Map */ Map<String, String> params = XmlHelper.getParams(ehElement); //判断emName是否为空 if (StringUtils.isEmpty(emName)) { emName = exceptionResult;//若为空则把result属性的值赋给emName } //新建一个ExceptionMappingConfig对象 ExceptionMappingConfig ehConfig = new ExceptionMappingConfig.Builder(emName, exceptionClassName, exceptionResult) .addParams(params) .location(DomHelper.getLocationObject(ehElement)) .build(); exceptionMappings.add(ehConfig); } } return exceptionMappings; }
为该action添加allow-method
/** * 创建allowed-method的Set * @param element * @param packageContext * @return */ protected Set<String> buildAllowedMethods(Element element, PackageConfig.Builder packageContext) { NodeList allowedMethodsEls = element.getElementsByTagName("allowed-methods");//获取该节点下面的所有的allowed-methods节点 Set<String> allowedMethods = null;//创建一个新的Set //如果allowed-methods的个数大于0 if (allowedMethodsEls.getLength() > 0) { allowedMethods = new HashSet<String>();//实例化该Set Node n = allowedMethodsEls.item(0).getFirstChild();//获取该allowed-methods的第一个子节点 //若其不为空,即存在 if (n != null) { String s = n.getNodeValue().trim();//获取该节点的值 if (s.length() > 0) { allowedMethods = TextParseUtil.commaDelimitedStringToSet(s); } } } else if (packageContext.isStrictMethodInvocation()) { allowedMethods = new HashSet<String>(); } //返回处理后的结果集 return allowedMethods; }
这些配置完成之后,把该action添加到packageContext中
然后调用:
//为该package加载默认的action
loadDefaultActionRef(newPackage, packageElement);
/** * 为action加载默认的default-action-ref * @param packageContext 包 * @param element 节点 */ protected void loadDefaultActionRef(PackageConfig.Builder packageContext, Element element) { NodeList resultTypeList = element.getElementsByTagName("default-action-ref");//获取该包下面的default-action-ref信息 if (resultTypeList.getLength() > 0) { Element defaultRefElement = (Element) resultTypeList.item(0);//获取第1个该default-action-ref节点 packageContext.defaultActionRef(defaultRefElement.getAttribute("name"));//把该节点的name放入package的defaultActionRef中 } }
在然后实例化该packageConfig对象,并添加到DefaultConfiguration中,返回该defaultConfiguration
②reloads.add(child);
如果配置需要重新更新的话,重新加载该package节点
③loadExtraConfiguration(doc);
该方法未执行任何操作,该方法内容具体如下:
/** * 运行子类加载document中的其他信息 * @param doc The configuration document */ protected void loadExtraConfiguration(Document doc) { // no op }
③loadExtraConfiguration(doc);//这三个方法没什么好介绍的
④reloadRequiredPackages(reloads);
⑤loadExtraConfiguration(doc);
至此,loadPackages方法执行结束
3:StrutsXmlConfigurationProvider(struts-plugin.xml)
同2:
4:StrutsXmlConfigurationProvider(struts.xml)
同2:
5:LegacyPropertiesConfigurationProvider
同1:
6:用户配置
具体情况具体分析
7:web.xml的filter中配置的参数
该方法是一个空实现
8:BeanSelectionProvider
该类中的该方法是一个空实现
19)packageProviders.add((PackageProvider)containerProvider);
把解析完之后的packageProvider放入packageProviders的list中
20)Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
根据类型来取得该类型的实例对象名称集合(适用于同一个类型创建了多个不同名称的对象)
21)PackageProvider provider = container.getInstance(PackageProvider.class, name);
22)provider.init(this);
23)provider.loadPackages();
24)packageProviders.add(provider);
25)rebuildRuntimeConfiguration();
27)return packageProviders;
这些代码,暂时未分析
②Container container = config.getContainer();
获取DefaultConfiguration实体对象的Container对象(此时的Container对象是一个ContainerImpl对象)
③boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
获取是否配置了国际化
④LocalizedTextUtil.setReloadBundles(reloadi18n);
定义是否需要重新装载资源绑定
4、加载完配置文件之后执行的操作
一:container.inject(this);
二:init_CheckConfigurationReloading(container);
/** * 在FileManager中设置是否需要重新加载 * @param container */ private void init_CheckConfigurationReloading(Container container) { //此时FileManager对象的实体是DefaultFileManager FileManager fileManager = container.getInstance(FileManager.class); fileManager.setReloadingConfigs("true".equals(container.getInstance(String.class, StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD))); }
三:init_CheckWebLogicWorkaround(container);
/** * 该方法具体内容暂时未分析 * @param container */ private void init_CheckWebLogicWorkaround(Container container) { // test whether param-access workaround needs to be enabled if (servletContext != null && servletContext.getServerInfo() != null && servletContext.getServerInfo().contains("WebLogic")) { if (LOG.isInfoEnabled()) { LOG.info("WebLogic server detected. Enabling Struts parameter access work-around."); } paramsWorkaroundEnabled = true; } else { paramsWorkaroundEnabled = "true".equals(container.getInstance(String.class, StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND)); } }
5、介绍StrutsPrepareAndExecuteFilter中剩余的部分
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);实例化一个prepare方法
这里的PrepareOperations类的构造方法如下:
/** * PrepareOperations的构造方法 * @param servletContext * @param dispatcher */ public PrepareOperations(ServletContext servletContext, Dispatcher dispatcher) { this.dispatcher = dispatcher;//实例化该类的内部变量dispatcher this.servletContext = servletContext;//实例化该类内部的变量servletContext }
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);实例化一个execute方法
这里的ExecuteOperations类的构造方法如下:
/** * ExecuteOperations的构造方法 * @param servletContext servletContext实例 * @param dispatcher dispatcher实例 */ public ExecuteOperations(ServletContext servletContext, Dispatcher dispatcher) { this.dispatcher = dispatcher;//实例化该类的内部变量dispatcher this.servletContext = servletContext;//实例化该类内部的变量servletContext }
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);执行buildExcludedPatternsList方法
该方法的具体含义目前不是很了解
postInit(dispatcher, filterConfig);//执行postInit方法
调用的StrutsPrepareAndExecuteFilter类中的postInit(Dispatcher dispatcher, FilterConfig filterConfig)方法如下:
/** * Callback for post initialization */ protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) { }
至此,struts2框架初始化结束
相关文章推荐
- Struts2源码粗略分析二:初始化详解
- struts2源码分析(一)(初始化)
- Struts2源码分析 初步1 --如何入手以及做了哪些初始化
- Struts2源码分析 初步2--Dispatcher初始化细节(1)
- struts2源码分析--IOC容器的实现(操作以及容器的初始化)
- Struts2初始化流程及源码分析
- struts2源码分析(二)(初始化)
- tomcat源码分析 StandardServer初始化过程
- Bochs源码分析-初始化部分
- 7 (phonegap源码分析) 平台相关模块和初始化(platform)
- Mesos源码分析(8): Mesos-Slave的初始化
- struts2请求过程源码分析
- Struts2 源码分析——配置管理之ContainerProvider接口
- springMVC源码分析--容器初始化(二)DispatcherServlet
- struts2源码分析笔记
- struts2 请求过程源码分析【精】
- android6.0源码分析之Runtime的初始化
- Java程序员从笨鸟到菜鸟之(四十)细谈struts2(四)struts2中action执行流程和源码分析
- struts2源码探索之初始化(三)
- Linux内核初始化过程的源码分析疑点记录+好书推荐(附下载)