接着第一篇,第一篇最后说道了在实际使用中会在生成一个运行时的configuration,进入com.opensymphony.xwork2.config.impl.DefaultConfiguration类的rebuildRuntimeConfiguration()方法,该方法就是专门用于生成运行时configuration的,F5进入:
public void rebuildRuntimeConfiguration() { runtimeConfiguration = buildRuntimeConfiguration(); }方法中再次调用了buildRuntimeConfiguration()方法,并将返回赋给runtimeConfiguration,runtimeConfiguration是DefaultConfiguration类中的一个属性,专门用于存放运行时configuration的。F5进入buildRuntimeConfiguration():
protected synchronized RuntimeConfiguration buildRuntimeConfiguration() throws ConfigurationException { Map<String, Map<String, ActionConfig>> namespaceActionConfigs = new LinkedHashMap<String, Map<String, ActionConfig>>(); Map<String, String> namespaceConfigs = new LinkedHashMap<String, String>(); for (PackageConfig packageConfig : packageContexts.values()) { if (!packageConfig.isAbstract()) { String namespace = packageConfig.getNamespace(); Map<String, ActionConfig> configs = namespaceActionConfigs.get(namespace); if (configs == null) { configs = new LinkedHashMap<String, ActionConfig>(); } Map<String, ActionConfig> actionConfigs = packageConfig.getAllActionConfigs(); for (Object o : actionConfigs.keySet()) { String actionName = (String) o; ActionConfig baseConfig = actionConfigs.get(actionName); configs.put(actionName, buildFullActionConfig(packageConfig, baseConfig)); } namespaceActionConfigs.put(namespace, configs); if (packageConfig.getFullDefaultActionRef() != null) { namespaceConfigs.put(namespace, packageConfig.getFullDefaultActionRef()); } } } return new RuntimeConfigurationImpl(namespaceActionConfigs, namespaceConfigs); }上面的方法就是真正完成生成工作的。第1、2句定义了俩个变量namespaceActionConfigs、namespaceConfigs,首先从变量名可以看出(注:我们要学会将变量名、类名、方法名这些东西当成注释看)namespaceActionConfigs是一个用于存放namespaceAction的config列表,即存放命名空间和action对应关系的结构(config),从它的Map的泛型参数<String, Map<String, ActionConfig>>中也可以看出,第一个String是存放namespace的,第二个Map<String, ActionConfig>是存放action的
集合,其中的String是action的name。第2个变量namespaceConfigs按照上面的分析发现其只是存放namespace的,实际上它的泛型参数<String, String>中,第一个String中存放namespace,第二个用于存放默认的action的name,即在配置文件中<default-action-ref>元素定义的。接着看下面的for语句,由第1篇文章中我们知道packageContexts中存放了从xml文档中解析的包配置。遍历packageContexts,if (!packageConfig.isAbstract()) 如果包不是抽象的,获得命名空间namespace,然后通过
namespaceActionConfigs.get(namespace)查看该命名空间是否在namespaceActionConfigs中存在,if (configs == null)如果不存在则生成个new LinkedHashMap<String, ActionConfig>(),用于存放具有相同命名空间的action的集合。接着通过packageConfig.getAllActionConfigs()得到该包中的所有antion,通过for循环将其添加到configs中,最后通过namespaceActionConfigs.put(namespace, configs)添加到namespaceActionConfigs中。最后的if (packageConfig.getFullDefaultActionRef() != null)是将该包中的默认action引用保存到该命名空间下,由于某一命名空间下只能存在一个默认action引用(default-action-ref),所以后面包中定义的会将前面包中的覆盖。方法最后通过return new RuntimeConfigurationImpl(namespaceActionConfigs, namespaceConfigs)生成个运行时configuration的实例,并将namespaceActionConfigs, namespaceConfigs俩个变量作为参数传入。这样整个运行时configuration就生成了。
这个运行时configuration在实际使用中也及在struts2处理http请求时,通过分析请求url,截取出命名空间namespace、action的name,通过这个命名空间namespace从运行时configuration中的namespaceActionConfigs属性中找到action列表,在通过
action的name从刚才找到的action列表中找到对应的action,由这个action去处理请求,这就是大概流程以及运行时configuration的实际作用。
写完之后才发现,这篇怎么这么少。