Struts2是一個優秀的MVC架構
Struts2的前端控制器為一個過濾器:
這在web.xml中配置:org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
前面我們已經知道了tomcat啟動的過程,tomcat啟動時,會初始化這個過濾器,調用init()方法:
public void init(FilterConfig filterConfig) throws ServletException { InitOperations init = new InitOperations(); try { FilterHostConfig config = new FilterHostConfig(filterConfig); init.initLogging(config); Dispatcher dispatcher = init.initDispatcher(config); init.initStaticContentLoader(config, dispatcher); prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher); execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);this.excludedPatterns = init.buildExcludedPatternsList(dispatcher); postInit(dispatcher, filterConfig); } finally { init.cleanup(); } }
我們注意到這段代碼:
Dispatcher dispatcher = init.initDispatcher(config);
其中,InitOperations類中的 initDispatcher(config)方法做了以下事情:
/** * Creates and initializes the dispatcher */ public Dispatcher initDispatcher( HostConfig filterConfig ) { Dispatcher dispatcher = createDispatcher(filterConfig); dispatcher.init(); return dispatcher; }
在這裡建立Dispatcher對象,並初始化,重點是dispatcher.init()方法,這個方法裡做了以下事情
public void init() { if (configurationManager == null) { configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME); } try { init_DefaultProperties(); // [1] init_TraditionalXmlConfigurations(); // [2] init_LegacyStrutsProperties(); // [3] init_CustomConfigurationProviders(); // [5] init_FilterInitParameters() ; // [6] init_AliasStandardObjects() ; // [7] Container container = init_PreloadConfiguration(); container.inject(this); init_CheckConfigurationReloading(container); init_CheckWebLogicWorkaround(container); if (!dispatcherListeners.isEmpty()) { for (DispatcherListener l : dispatcherListeners) { l.dispatcherInitialized(this); } } } catch (Exception ex) { if (LOG.isErrorEnabled()) LOG.error("Dispatcher initialization failed", ex); throw new StrutsException(ex); } }
init_DefaultProperties()這個方法載入了org/apache/struts2/default.properties檔案;
init_TraditionalXmlConfigurations();這個方法裡,我們可以看到:
private void init_TraditionalXmlConfigurations() { String configPaths = initParams.get("config"); if (configPaths == null) { configPaths = DEFAULT_CONFIGURATION_PATHS; } String[] files = configPaths.split("\\s*[,]\\s*"); 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"); } } }
DEFAULT_CONFIGURATION_PATHS是什麼呢??
private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";
實際上,在這裡載入了上面三個預設的設定檔,這幾個設定檔中,如果有相同的元素,按照載入順序後者覆蓋前者。
因此我們可以在通過struts-plugin.xml檔案整合其他外掛程式,外掛程式以jar包的形式,並且jar包中藥包含struts-plugin.xml檔案。
我們可以在sturts.xml檔案中對struts2進行各種配置,通過include將其他struts2設定檔包含。
init_PreloadConfiguration()方法中對載入的設定檔進行解析:
private Container init_PreloadConfiguration() { Configuration config = configurationManager.getConfiguration(); Container container = config.getContainer(); boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD)); LocalizedTextUtil.setReloadBundles(reloadi18n); return container; }
configurationManager.getConfiguration()
public synchronized Configuration getConfiguration() { if (configuration == null) { setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName)); try { configuration.reloadContainer(getContainerProviders()); } catch (ConfigurationException e) { setConfiguration(null); throw new ConfigurationException("Unable to load configuration.", e); } } else { conditionalReload(); } return configuration; }
configuration.reloadContainer(getContainerProviders()):解析設定檔
/** * Calls the ConfigurationProviderFactory.getConfig() to tell it to reload the configuration and then calls * buildRuntimeConfiguration(). * * @throws ConfigurationException */ public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException
這個方法太長,就不放上來了。
結果以上這些,struts2中的各種配置全部載入解析完成。