读书人

struts 二

发布时间: 2012-08-11 20:50:31 作者: rapoo

struts 2

1. Struts2架构图
??????? 请求首先通过Filter chain,Filter主要包括ActionContextCleanUp,它主要清理当前线程的ActionContext和Dispatcher;FilterDispatcher主要通过AcionMapper来决定需要调用哪个Action。Java代码

  1. //创—ispatcher,此类是一个Delegate,它是真正完成根据url解析,读取对应Action的地方public?void?init(FilterConfig?filterConfig)?throws?ServletException?{ ??
  2. ????try?{ ??
  3. ????????this.filterConfig?=?filterConfig; ??
  4. ??
  5. ????????initLogging(); ??
  6. ??
  7. ????????dispatcher?=?createDispatcher(filterConfig); ??
  8. ????????dispatcher.init(); ??
  9. ????????dispatcher.getContainer().inject(this); ??
  10. ????????//读取初始参数pakages,调用parse(),解析成类似/org/apache/struts2/static,/template的数组"packages"); ??
  11. ????????String?packages?=?"org.apache.struts2.static?template?org.apache.struts2.interceptor.debugging"; ??
  12. ????????if?(param?!=?null)?{ ??
  13. ????????????packages?=?param?+?"?"?+?packages; ??
  14. ????????} ??
  15. ????????this.pathPrefixes?=?parse(packages); ??
  16. ????}?finally?{ ??
  17. ????????ActionContext.setContext(null); ??
  18. ????} ??
  19. }??
Java代码
  1. //创—ispatcher,此类是一个Delegate,它是真正完成根据url解析,读取对应Action的地方??
  2. public?void?init(FilterConfig?filterConfig)?throws?ServletException?{??
  3. ????try?{??
  4. ????????this.filterConfig?=?filterConfig;??
  5. ??
  6. ????????initLogging();??
  7. ??
  8. ????????dispatcher?=?createDispatcher(filterConfig);??
  9. ????????dispatcher.init();??
  10. ????????dispatcher.getContainer().inject(this);??
  11. ????????//读取初始参数pakages,调用parse(),解析成类似/org/apache/struts2/static,/template的数组??
  12. ????????String?param?=?filterConfig.getInitParameter("packages");??
  13. ????????String?packages?=?"org.apache.struts2.static?template?org.apache.struts2.interceptor.debugging";??
  14. ????????if?(param?!=?null)?{??
  15. ????????????packages?=?param?+?"?"?+?packages;??
  16. ????????}??
  17. ????????this.pathPrefixes?=?parse(packages);??
  18. ????}?finally?{??
  19. ????????ActionContext.setContext(null);??
  20. ????}??
  21. }??


???? 顺着流程我们看Disptcher的init方法。init方法里就是初始读取一些配置文件等,先看init_DefaultProperties,主要是读取properties配置文件。

Java代码
  1. private?void?init_DefaultProperties()?{ ??
  2. ????configurationManager.addConfigurationProvider(new?DefaultPropertiesProvider()); ??
  3. }??
Java代码
  1. private?void?init_DefaultProperties()?{??
  2. ????configurationManager.addConfigurationProvider(new?DefaultPropertiesProvider());??
  3. }??


??? 打开DefaultPropertiesProvider

Java代码
  1. public?void?register(ContainerBuilder?builder,?LocatableProperties?props) ??
  2. ?????????throws?ConfigurationException?{ ??
  3. ????? ??
  4. ?????Settings?defaultSettings?=?null; ??
  5. ?????try?{ ??
  6. ?????????defaultSettings?=?new?PropertiesSettings("org/apache/struts2/default"); ??
  7. ?????}?catch?(Exception?e)?{ ??
  8. ?????????throw?new?ConfigurationException("Could?not?find?or?error?in?org/apache/struts2/default.properties",?e); ??
  9. ?????} ??
  10. ????? ??
  11. ?????loadSettings(props,?defaultSettings); ??
  12. ?} ??
  13. ??
  14. ?//PropertiesSettings//读取org/apache/struts2/default.properties的配置信息,如果项目中需要覆盖,可以在classpath里的struts.properties里覆写public?PropertiesSettings(String?name)?{ ??
  15. ????? ??
  16. ?????URL?settingsUrl?=?ClassLoaderUtils.getResource(name?+?".properties",?getClass()); ??
  17. ????? ??
  18. ?????if?(settingsUrl?==?null)?{ ??
  19. ?????????LOG.debug(name?+?".properties?missing"); ??
  20. ?????????settings?=?new?LocatableProperties(); ??
  21. ?????????return; ??
  22. ?????} ??
  23. ????? ??
  24. ?????settings?=?new?LocatableProperties(new?LocationImpl(null,?settingsUrl.toString())); ??
  25. ??
  26. ?????//?Load?settingsnull; ??
  27. ?????try?{ ??
  28. ?????????in?=?settingsUrl.openStream(); ??
  29. ?????????settings.load(in); ??
  30. ?????}?catch?(IOException?e)?{ ??
  31. ?????????throw?new?StrutsException("Could?not?load?"?+?name?+?".properties:"?+?e,?e); ??
  32. ?????}?finally?{ ??
  33. ?????????if(in?!=?null)?{ ??
  34. ?????????????try?{ ??
  35. ?????????????????in.close(); ??
  36. ?????????????}?catch(IOException?io)?{ ??
  37. ?????????????????LOG.warn("Unable?to?close?input?stream",?io); ??
  38. ?????????????} ??
  39. ?????????} ??
  40. ?????} ??
  41. ?}??
Java代码
  1. public?void?register(ContainerBuilder?builder,?LocatableProperties?props)??
  2. ?????????throws?ConfigurationException?{??
  3. ???????
  4. ?????Settings?defaultSettings?=?null;??
  5. ?????try?{??
  6. ?????????defaultSettings?=?new?PropertiesSettings("org/apache/struts2/default");??
  7. ?????}?catch?(Exception?e)?{??
  8. ?????????throw?new?ConfigurationException("Could?not?find?or?error?in?org/apache/struts2/default.properties",?e);??
  9. ?????}??
  10. ???????
  11. ?????loadSettings(props,?defaultSettings);??
  12. ?}??
  13. ??
  14. ?//PropertiesSettings??
  15. ?//读取org/apache/struts2/default.properties的配置信息,如果项目中需要覆盖,可以在classpath里的struts.properties里覆写??
  16. ?public?PropertiesSettings(String?name)?{??
  17. ???????
  18. ?????URL?settingsUrl?=?ClassLoaderUtils.getResource(name?+?".properties",?getClass());??
  19. ???????
  20. ?????if?(settingsUrl?==?null)?{??
  21. ?????????LOG.debug(name?+?".properties?missing");??
  22. ?????????settings?=?new?LocatableProperties();??
  23. ?????????return;??
  24. ?????}??
  25. ???????
  26. ?????settings?=?new?LocatableProperties(new?LocationImpl(null,?settingsUrl.toString()));??
  27. ??
  28. ?????//?Load?settings??
  29. ?????InputStream?in?=?null;??
  30. ?????try?{??
  31. ?????????in?=?settingsUrl.openStream();??
  32. ?????????settings.load(in);??
  33. ?????}?catch?(IOException?e)?{??
  34. ?????????throw?new?StrutsException("Could?not?load?"?+?name?+?".properties:"?+?e,?e);??
  35. ?????}?finally?{??
  36. ?????????if(in?!=?null)?{??
  37. ?????????????try?{??
  38. ?????????????????in.close();??
  39. ?????????????}?catch(IOException?io)?{??
  40. ?????????????????LOG.warn("Unable?to?close?input?stream",?io);??
  41. ?????????????}??
  42. ?????????}??
  43. ?????}??
  44. ?}??


??? 再来看init_TraditionalXmlConfigurations方法,这个是读取struts-default.xml和Struts.xml的方法。

Java代码
  1. private?void?init_TraditionalXmlConfigurations()?{ ??
  2. ????//首先读取web.xml中的config初始参数值//如果没有配置就使用默认的"struts-default.xml,struts-plugin.xml,struts.xml",//这儿就可以看出为什么默认的配置文件必须取名为这三个名称了//如果不想使用默认的名称,直接在web.xml中配置config初始参数即可"config"); ??
  3. ????if?(configPaths?==?null)?{ ??
  4. ????????configPaths?=?DEFAULT_CONFIGURATION_PATHS; ??
  5. ????} ??
  6. ????String[]?files?=?configPaths.split("\\s*[,]\\s*"); ??
  7. ????//依次解析配置文件,xwork.xml单独解析for?(String?file?:?files)?{ ??
  8. ????????if?(file.endsWith(".xml"))?{ ??
  9. ????????????if?("xwork.xml".equals(file))?{ ??
  10. ????????????????configurationManager.addConfigurationProvider(new?XmlConfigurationProvider(file,?false)); ??
  11. ????????????}?else?{ ??
  12. ????????????????configurationManager.addConfigurationProvider(new?StrutsXmlConfigurationProvider(file,?false,?servletContext)); ??
  13. ????????????} ??
  14. ????????}?else?{ ??
  15. ????????????throw?new?IllegalArgumentException("Invalid?configuration?file?name"); ??
  16. ????????} ??
  17. ????} ??
  18. }??
Java代码
  1. private?void?init_TraditionalXmlConfigurations()?{??
  2. ????//首先读取web.xml中的config初始参数值??
  3. ????//如果没有配置就使用默认的"struts-default.xml,struts-plugin.xml,struts.xml",??
  4. ????//这儿就可以看出为什么默认的配置文件必须取名为这三个名称了??
  5. ????//如果不想使用默认的名称,直接在web.xml中配置config初始参数即可??
  6. ????String?configPaths?=?initParams.get("config");??
  7. ????if?(configPaths?==?null)?{??
  8. ????????configPaths?=?DEFAULT_CONFIGURATION_PATHS;??
  9. ????}??
  10. ????String[]?files?=?configPaths.split("\\s*[,]\\s*");??
  11. ????//依次解析配置文件,xwork.xml单独解析??
  12. ????for?(String?file?:?files)?{??
  13. ????????if?(file.endsWith(".xml"))?{??
  14. ????????????if?("xwork.xml".equals(file))?{??
  15. ????????????????configurationManager.addConfigurationProvider(new?XmlConfigurationProvider(file,?false));??
  16. ????????????}?else?{??
  17. ????????????????configurationManager.addConfigurationProvider(new?StrutsXmlConfigurationProvider(file,?false,?servletContext));??
  18. ????????????}??
  19. ????????}?else?{??
  20. ????????????throw?new?IllegalArgumentException("Invalid?configuration?file?name");??
  21. ????????}??
  22. ????}??
  23. }??


??? 对于其它配置文件只用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代码
  1. protected?PackageConfig?addPackage(Element?packageElement)?throws?ConfigurationException?{ ??
  2. ????PackageConfig.Builder?newPackage?=?buildPackageContext(packageElement); ??
  3. ??
  4. ????if?(newPackage.isNeedsRefresh())?{ ??
  5. ????????return?newPackage.build(); ??
  6. ????} ??
  7. ????. ??
  8. ??
  9. ????addResultTypes(newPackage,?packageElement); ??
  10. ????loadInterceptors(newPackage,?packageElement); ??
  11. ????loadDefaultInterceptorRef(newPackage,?packageElement); ??
  12. ????loadDefaultClassRef(newPackage,?packageElement); ??
  13. ????loadGlobalResults(newPackage,?packageElement); ??
  14. ????loadGobalExceptionMappings(newPackage,?packageElement); ??
  15. ????NodeList?actionList?=?packageElement.getElementsByTagName("action"); ??
  16. ??
  17. ????for?(int?i?=?0;?i?<?actionList.getLength();?i++)?{ ??
  18. ????????Element?actionElement?=?(Element)?actionList.item(i); ??
  19. ????????addAction(actionElement,?newPackage); ??
  20. ????} ??
  21. ????loadDefaultActionRef(newPackage,?packageElement); ??
  22. ????PackageConfig?cfg?=?newPackage.build(); ??
  23. ????configuration.addPackageConfig(cfg.getName(),?cfg); ??
  24. ????return?cfg; ??
  25. }??
Java代码
  1. protected?PackageConfig?addPackage(Element?packageElement)?throws?ConfigurationException?{??
  2. ????PackageConfig.Builder?newPackage?=?buildPackageContext(packageElement);??
  3. ??
  4. ????if?(newPackage.isNeedsRefresh())?{??
  5. ????????return?newPackage.build();??
  6. ????}??
  7. ????.??
  8. ??
  9. ????addResultTypes(newPackage,?packageElement);??
  10. ????loadInterceptors(newPackage,?packageElement);??
  11. ????loadDefaultInterceptorRef(newPackage,?packageElement);??
  12. ????loadDefaultClassRef(newPackage,?packageElement);??
  13. ????loadGlobalResults(newPackage,?packageElement);??
  14. ????loadGobalExceptionMappings(newPackage,?packageElement);??
  15. ????NodeList?actionList?=?packageElement.getElementsByTagName("action");??
  16. ??
  17. ????for?(int?i?=?0;?i?<?actionList.getLength();?i++)?{??
  18. ????????Element?actionElement?=?(Element)?actionList.item(i);??
  19. ????????addAction(actionElement,?newPackage);??
  20. ????}??
  21. ????loadDefaultActionRef(newPackage,?packageElement);??
  22. ????PackageConfig?cfg?=?newPackage.build();??
  23. ????configuration.addPackageConfig(cfg.getName(),?cfg);??
  24. ????return?cfg;??
  25. }??


??? 这儿发现一个配置上的小技巧,我的xwork2.0.*是没有的,但是看源码是看到xwork2.1.*是可以的。继续看XmlConfigurationProvider的源代码:

Java代码
  1. private?List?loadConfigurationFiles(String?fileName,?Element?includeElement)?{ ??
  2. ????List<Document>?docs?=?new?ArrayList<Document>(); ??
  3. ????if?(!includedFileNames.contains(fileName))?{ ??
  4. ???????????? ??
  5. ????????????Element?rootElement?=?doc.getDocumentElement(); ??
  6. ????????????NodeList?children?=?rootElement.getChildNodes(); ??
  7. ????????????int?childSize?=?children.getLength(); ??
  8. ??
  9. ????????????for?(int?i?=?0;?i?<?childSize;?i++)?{ ??
  10. ????????????????Node?childNode?=?children.item(i); ??
  11. ??
  12. ????????????????if?(childNode?instanceof?Element)?{ ??
  13. ????????????????????Element?child?=?(Element)?childNode; ??
  14. ??
  15. ????????????????????final?String?nodeName?=?child.getNodeName(); ??
  16. ????????????????????//解析每个action配置是,对于include文件可以使用通配符*来进行配置//如Struts.xml中可配置成<include?file="actions_*.xml"/>if?(nodeName.equals("include"))?{ ??
  17. ????????????????????????String?includeFileName?=?child.getAttribute("file"); ??
  18. ????????????????????????if(includeFileName.indexOf('*')?!=?-1?)?{ ??
  19. ????????????????????????????ClassPathFinder?wildcardFinder?=?new?ClassPathFinder(); ??
  20. ????????????????????????????wildcardFinder.setPattern(includeFileName); ??
  21. ????????????????????????????Vector<String>?wildcardMatches?=?wildcardFinder.findMatches(); ??
  22. ????????????????????????????for?(String?match?:?wildcardMatches)?{ ??
  23. ????????????????????????????????docs.addAll(loadConfigurationFiles(match,?child)); ??
  24. ????????????????????????????} ??
  25. ????????????????????????} ??
  26. ????????????????????????else?{ ??
  27. ???????????????????????????? ??
  28. ????????????????????????????docs.addAll(loadConfigurationFiles(includeFileName,?child));???? ??
  29. ????????????????????????}???? ??
  30. ????????????????} ??
  31. ????????????} ??
  32. ????????????} ??
  33. ????????????docs.add(doc); ??
  34. ????????????loadedFileUrls.add(url.toString()); ??
  35. ????????} ??
  36. ????} ??
  37. ????return?docs; ??
  38. }??

读书人网 >开源软件

热点推荐