struts 二
struts 21. Struts2架构图??????? 请求首先通过Filter chain,Filter主要包括ActionContextCleanUp,它主要
struts 2
1. Struts2架构图
??????? 请求首先通过Filter chain,Filter主要包括ActionContextCleanUp,它主要清理当前线程的ActionContext和Dispatcher;FilterDispatcher主要通过AcionMapper来决定需要调用哪个Action。Java代码
- //创建Dispatcher,此类是一个Delegate,它是真正完成根据url解析,读取对应Action的地方public?void?init(FilterConfig?filterConfig)?throws?ServletException?{ ??
- ????try?{ ??
- ????????this.filterConfig?=?filterConfig; ??
- ??
- ????????initLogging(); ??
- ??
- ????????dispatcher?=?createDispatcher(filterConfig); ??
- ????????dispatcher.init(); ??
- ????????dispatcher.getContainer().inject(this); ??
- ????????//读取初始参数pakages,调用parse(),解析成类似/org/apache/struts2/static,/template的数组"packages"); ??
- ????????String?packages?=?"org.apache.struts2.static?template?org.apache.struts2.interceptor.debugging"; ??
- ????????if?(param?!=?null)?{ ??
- ????????????packages?=?param?+?"?"?+?packages; ??
- ????????} ??
- ????????this.pathPrefixes?=?parse(packages); ??
- ????}?finally?{ ??
- ????????ActionContext.setContext(null); ??
- ????} ??
- }??
Java代码
- //创建Dispatcher,此类是一个Delegate,它是真正完成根据url解析,读取对应Action的地方??
- public?void?init(FilterConfig?filterConfig)?throws?ServletException?{??
- ????try?{??
- ????????this.filterConfig?=?filterConfig;??
- ??
- ????????initLogging();??
- ??
- ????????dispatcher?=?createDispatcher(filterConfig);??
- ????????dispatcher.init();??
- ????????dispatcher.getContainer().inject(this);??
- ????????//读取初始参数pakages,调用parse(),解析成类似/org/apache/struts2/static,/template的数组??
- ????????String?param?=?filterConfig.getInitParameter("packages");??
- ????????String?packages?=?"org.apache.struts2.static?template?org.apache.struts2.interceptor.debugging";??
- ????????if?(param?!=?null)?{??
- ????????????packages?=?param?+?"?"?+?packages;??
- ????????}??
- ????????this.pathPrefixes?=?parse(packages);??
- ????}?finally?{??
- ????????ActionContext.setContext(null);??
- ????}??
- }??
???? 顺着流程我们看Disptcher的init方法。init方法里就是初始读取一些配置文件等,先看init_DefaultProperties,主要是读取properties配置文件。
Java代码
- private?void?init_DefaultProperties()?{ ??
- ????configurationManager.addConfigurationProvider(new?DefaultPropertiesProvider()); ??
- }??
Java代码
- private?void?init_DefaultProperties()?{??
- ????configurationManager.addConfigurationProvider(new?DefaultPropertiesProvider());??
- }??
??? 打开DefaultPropertiesProvider
Java代码
- public?void?register(ContainerBuilder?builder,?LocatableProperties?props) ??
- ?????????throws?ConfigurationException?{ ??
- ????? ??
- ?????Settings?defaultSettings?=?null; ??
- ?????try?{ ??
- ?????????defaultSettings?=?new?PropertiesSettings("org/apache/struts2/default"); ??
- ?????}?catch?(Exception?e)?{ ??
- ?????????throw?new?ConfigurationException("Could?not?find?or?error?in?org/apache/struts2/default.properties",?e); ??
- ?????} ??
- ????? ??
- ?????loadSettings(props,?defaultSettings); ??
- ?} ??
- ??
- ?//PropertiesSettings//读取org/apache/struts2/default.properties的配置信息,如果项目中需要覆盖,可以在classpath里的struts.properties里覆写public?PropertiesSettings(String?name)?{ ??
- ????? ??
- ?????URL?settingsUrl?=?ClassLoaderUtils.getResource(name?+?".properties",?getClass()); ??
- ????? ??
- ?????if?(settingsUrl?==?null)?{ ??
- ?????????LOG.debug(name?+?".properties?missing"); ??
- ?????????settings?=?new?LocatableProperties(); ??
- ?????????return; ??
- ?????} ??
- ????? ??
- ?????settings?=?new?LocatableProperties(new?LocationImpl(null,?settingsUrl.toString())); ??
- ??
- ?????//?Load?settingsnull; ??
- ?????try?{ ??
- ?????????in?=?settingsUrl.openStream(); ??
- ?????????settings.load(in); ??
- ?????}?catch?(IOException?e)?{ ??
- ?????????throw?new?StrutsException("Could?not?load?"?+?name?+?".properties:"?+?e,?e); ??
- ?????}?finally?{ ??
- ?????????if(in?!=?null)?{ ??
- ?????????????try?{ ??
- ?????????????????in.close(); ??
- ?????????????}?catch(IOException?io)?{ ??
- ?????????????????LOG.warn("Unable?to?close?input?stream",?io); ??
- ?????????????} ??
- ?????????} ??
- ?????} ??
- ?}??
Java代码
- public?void?register(ContainerBuilder?builder,?LocatableProperties?props)??
- ?????????throws?ConfigurationException?{??
- ???????
- ?????Settings?defaultSettings?=?null;??
- ?????try?{??
- ?????????defaultSettings?=?new?PropertiesSettings("org/apache/struts2/default");??
- ?????}?catch?(Exception?e)?{??
- ?????????throw?new?ConfigurationException("Could?not?find?or?error?in?org/apache/struts2/default.properties",?e);??
- ?????}??
- ???????
- ?????loadSettings(props,?defaultSettings);??
- ?}??
- ??
- ?//PropertiesSettings??
- ?//读取org/apache/struts2/default.properties的配置信息,如果项目中需要覆盖,可以在classpath里的struts.properties里覆写??
- ?public?PropertiesSettings(String?name)?{??
- ???????
- ?????URL?settingsUrl?=?ClassLoaderUtils.getResource(name?+?".properties",?getClass());??
- ???????
- ?????if?(settingsUrl?==?null)?{??
- ?????????LOG.debug(name?+?".properties?missing");??
- ?????????settings?=?new?LocatableProperties();??
- ?????????return;??
- ?????}??
- ???????
- ?????settings?=?new?LocatableProperties(new?LocationImpl(null,?settingsUrl.toString()));??
- ??
- ?????//?Load?settings??
- ?????InputStream?in?=?null;??
- ?????try?{??
- ?????????in?=?settingsUrl.openStream();??
- ?????????settings.load(in);??
- ?????}?catch?(IOException?e)?{??
- ?????????throw?new?StrutsException("Could?not?load?"?+?name?+?".properties:"?+?e,?e);??
- ?????}?finally?{??
- ?????????if(in?!=?null)?{??
- ?????????????try?{??
- ?????????????????in.close();??
- ?????????????}?catch(IOException?io)?{??
- ?????????????????LOG.warn("Unable?to?close?input?stream",?io);??
- ?????????????}??
- ?????????}??
- ?????}??
- ?}??
??? 再来看init_TraditionalXmlConfigurations方法,这个是读取struts-default.xml和Struts.xml的方法。
Java代码
- private?void?init_TraditionalXmlConfigurations()?{ ??
- ????//首先读取web.xml中的config初始参数值//如果没有配置就使用默认的"struts-default.xml,struts-plugin.xml,struts.xml",//这儿就可以看出为什么默认的配置文件必须取名为这三个名称了//如果不想使用默认的名称,直接在web.xml中配置config初始参数即可"config"); ??
- ????if?(configPaths?==?null)?{ ??
- ????????configPaths?=?DEFAULT_CONFIGURATION_PATHS; ??
- ????} ??
- ????String[]?files?=?configPaths.split("\\s*[,]\\s*"); ??
- ????//依次解析配置文件,xwork.xml单独解析for?(String?file?:?files)?{ ??
- ????????if?(file.endsWith(".xml"))?{ ??
- ????????????if?("xwork.xml".equals(file))?{ ??
- ????????????????configurationManager.addConfigurationProvider(new?XmlConfigurationProvider(file,?false)); ??
- ????????????}?else?{ ??
- ????????????????configurationManager.addConfigurationProvider(new?StrutsXmlConfigurationProvider(file,?false,?servletContext)); ??
- ????????????} ??
- ????????}?else?{ ??
- ????????????throw?new?IllegalArgumentException("Invalid?configuration?file?name"); ??
- ????????} ??
- ????} ??
- }??
Java代码
- private?void?init_TraditionalXmlConfigurations()?{??
- ????//首先读取web.xml中的config初始参数值??
- ????//如果没有配置就使用默认的"struts-default.xml,struts-plugin.xml,struts.xml",??
- ????//这儿就可以看出为什么默认的配置文件必须取名为这三个名称了??
- ????//如果不想使用默认的名称,直接在web.xml中配置config初始参数即可??
- ????String?configPaths?=?initParams.get("config");??
- ????if?(configPaths?==?null)?{??
- ????????configPaths?=?DEFAULT_CONFIGURATION_PATHS;??
- ????}??
- ????String[]?files?=?configPaths.split("\\s*[,]\\s*");??
- ????//依次解析配置文件,xwork.xml单独解析??
- ????for?(String?file?:?files)?{??
- ????????if?(file.endsWith(".xml"))?{??
- ????????????if?("xwork.xml".equals(file))?{??
- ????????????????configurationManager.addConfigurationProvider(new?XmlConfigurationProvider(file,?false));??
- ????????????}?else?{??
- ????????????????configurationManager.addConfigurationProvider(new?StrutsXmlConfigurationProvider(file,?false,?servletContext));??
- ????????????}??
- ????????}?else?{??
- ????????????throw?new?IllegalArgumentException("Invalid?configuration?file?name");??
- ????????}??
- ????}??
- }??
??? 对于其它配置文件只用StrutsXmlConfigurationProvider,此类继承XmlConfigurationProvider,而XmlConfigurationProvider又实现ConfigurationProvider接口。类XmlConfigurationProvider负责配置文件的读取和解析,addAction()方法负责读取<action>标签,并将数据保存在ActionConfig中;addResultTypes()方法负责将<result-type>标签转化为ResultTypeConfig对象;loadInterceptors()方法负责将<interceptor>标签转化为InterceptorConfi对象;loadInterceptorStack()方法负责将<interceptor-ref>标签转化为InterceptorStackConfig对象;loadInterceptorStacks()方法负责将<interceptor-stack>标签转化成InterceptorStackConfig对象。而上面的方法最终会被addPackage()方法调用,将所读取到的数据汇集到PackageConfig对象中。来看XmlConfigurationProvider的源代码,详细的我自己也就大体浏览了一下,各位可以自己研读。
Java代码
- protected?PackageConfig?addPackage(Element?packageElement)?throws?ConfigurationException?{ ??
- ????PackageConfig.Builder?newPackage?=?buildPackageContext(packageElement); ??
- ??
- ????if?(newPackage.isNeedsRefresh())?{ ??
- ????????return?newPackage.build(); ??
- ????} ??
- ????. ??
- ??
- ????addResultTypes(newPackage,?packageElement); ??
- ????loadInterceptors(newPackage,?packageElement); ??
- ????loadDefaultInterceptorRef(newPackage,?packageElement); ??
- ????loadDefaultClassRef(newPackage,?packageElement); ??
- ????loadGlobalResults(newPackage,?packageElement); ??
- ????loadGobalExceptionMappings(newPackage,?packageElement); ??
- ????NodeList?actionList?=?packageElement.getElementsByTagName("action"); ??
- ??
- ????for?(int?i?=?0;?i?<?actionList.getLength();?i++)?{ ??
- ????????Element?actionElement?=?(Element)?actionList.item(i); ??
- ????????addAction(actionElement,?newPackage); ??
- ????} ??
- ????loadDefaultActionRef(newPackage,?packageElement); ??
- ????PackageConfig?cfg?=?newPackage.build(); ??
- ????configuration.addPackageConfig(cfg.getName(),?cfg); ??
- ????return?cfg; ??
- }??
Java代码
- protected?PackageConfig?addPackage(Element?packageElement)?throws?ConfigurationException?{??
- ????PackageConfig.Builder?newPackage?=?buildPackageContext(packageElement);??
- ??
- ????if?(newPackage.isNeedsRefresh())?{??
- ????????return?newPackage.build();??
- ????}??
- ????.??
- ??
- ????addResultTypes(newPackage,?packageElement);??
- ????loadInterceptors(newPackage,?packageElement);??
- ????loadDefaultInterceptorRef(newPackage,?packageElement);??
- ????loadDefaultClassRef(newPackage,?packageElement);??
- ????loadGlobalResults(newPackage,?packageElement);??
- ????loadGobalExceptionMappings(newPackage,?packageElement);??
- ????NodeList?actionList?=?packageElement.getElementsByTagName("action");??
- ??
- ????for?(int?i?=?0;?i?<?actionList.getLength();?i++)?{??
- ????????Element?actionElement?=?(Element)?actionList.item(i);??
- ????????addAction(actionElement,?newPackage);??
- ????}??
- ????loadDefaultActionRef(newPackage,?packageElement);??
- ????PackageConfig?cfg?=?newPackage.build();??
- ????configuration.addPackageConfig(cfg.getName(),?cfg);??
- ????return?cfg;??
- }??
??? 这儿发现一个配置上的小技巧,我的xwork2.0.*是没有的,但是看源码是看到xwork2.1.*是可以的。继续看XmlConfigurationProvider的源代码:
Java代码
- private?List?loadConfigurationFiles(String?fileName,?Element?includeElement)?{ ??
- ????List<Document>?docs?=?new?ArrayList<Document>(); ??
- ????if?(!includedFileNames.contains(fileName))?{ ??
- ???????????? ??
- ????????????Element?rootElement?=?doc.getDocumentElement(); ??
- ????????????NodeList?children?=?rootElement.getChildNodes(); ??
- ????????????int?childSize?=?children.getLength(); ??
- ??
- ????????????for?(int?i?=?0;?i?<?childSize;?i++)?{ ??
- ????????????????Node?childNode?=?children.item(i); ??
- ??
- ????????????????if?(childNode?instanceof?Element)?{ ??
- ????????????????????Element?child?=?(Element)?childNode; ??
- ??
- ????????????????????final?String?nodeName?=?child.getNodeName(); ??
- ????????????????????//解析每个action配置是,对于include文件可以使用通配符*来进行配置//如Struts.xml中可配置成<include?file="actions_*.xml"/>if?(nodeName.equals("include"))?{ ??
- ????????????????????????String?includeFileName?=?child.getAttribute("file"); ??
- ????????????????????????if(includeFileName.indexOf('*')?!=?-1?)?{ ??
- ????????????????????????????ClassPathFinder?wildcardFinder?=?new?ClassPathFinder(); ??
- ????????????????????????????wildcardFinder.setPattern(includeFileName); ??
- ????????????????????????????Vector<String>?wildcardMatches?=?wildcardFinder.findMatches(); ??
- ????????????????????????????for?(String?match?:?wildcardMatches)?{ ??
- ????????????????????????????????docs.addAll(loadConfigurationFiles(match,?child)); ??
- ????????????????????????????} ??
- ????????????????????????} ??
- ????????????????????????else?{ ??
- ???????????????????????????? ??
- ????????????????????????????docs.addAll(loadConfigurationFiles(includeFileName,?child));???? ??
- ????????????????????????}???? ??
- ????????????????} ??
- ????????????} ??
- ????????????} ??
- ????????????docs.add(doc); ??
- ????????????loadedFileUrls.add(url.toString()); ??
- ????????} ??
- ????} ??
- ????return?docs; ??
- }??