Dispatcher是Struts2的核心分發器,就比如SpringMVC的DispatcherServlet,它是完成url解析轉向,讀取對應Action的地方,至關於一個路由。 css
先看一段代碼: java
private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();能夠看到,Dispatcher也是使用ThreadLocal模式。在Struts2中大量使用了ThreadLocal模式,好比上次說到的ActionContext。
建立Dispatcher: web
public Dispatcher(ServletContext servletContext, Map<String, String> initParams) { this.servletContext = servletContext; this.initParams = initParams; }
initParams配置在web.xml中的param參數. app
接下來,主要會闡述init,serviceAction,cleanup這三個方法。 ide
init方法的主要工做是初始化配置文件,它會分七步載入各類配置文件,都是經過ConfigurationProvider接口進行的,這個接口提供init(),destroy(),register()等方法.。將各類ConfigurationProvider初始化以後將實例添加到ConfigurationManager的List裏面,最後經過循環調用List裏的這些destroy(),register()等方法實現對配置文件的屬性進行註冊和銷燬等功能。 this
init_DefaultProperties(); // [1]
private void init_DefaultProperties() { configurationManager.addContainerProvider(new DefaultPropertiesProvider()); }
DefaultPropertiesProvider:讀取properties信息,默認是default.properties url
init_TraditionalXmlConfigurations(); // [2]讀取xml配置文件這裏面會涉及到兩個類XmlConfigurationProvider,StrutsXmlConfigurationProvider,後者是前者的子類。XmlConfigurationProvider負責解析xwork.xml,其它xml文件由StrutsXmlConfigurationProvider解析。
init_LegacyStrutsProperties();LegacyPropertiesConfigurationProvider負責讀取用戶自定義的struts.properties文件信息。該類繼承自DefaultPropertiesProvider。
源碼註釋直接第五步,我一直沒找到第四步在哪,還請大俠們指教。 spa
init_CustomConfigurationProviders(); // [5]讀取自定義的configProviders
init_FilterInitParameters() ; // [6]載入FilterDispatcher傳進來的initParams
init_AliasStandardObjects() ; // [7]將配置文件中的bean與具體的類映射到這裏配置文件都已經加載完成,可是尚未註冊。
Container container = init_PreloadConfiguration();init_PreloadConfiguration方法中會執行:
Configuration config = configurationManager.getConfiguration();順着這條鏈,會在DefaultConfiguration中找到reloadContainer方法。就像最初說的,這裏會遍歷providers,而且調用 ConfigurationProvider的register方法進行註冊。
直接貼代碼吧。 代理
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionMapping mapping) throws ServletException { //createContextMap方法主要把Application、Session、Request的key value值拷貝到Map中 Map<String, Object> extraContext = createContextMap(request, response, mapping, context); //這裏省略的部分代碼 String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod(); Configuration config = configurationManager.getConfiguration(); //建立一個Action的代理對象,ActionProxyFactory是建立ActionProxy的工廠 //參考實現類:DefaultActionProxy和DefaultActionProxyFactory ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( namespace, name, method, extraContext, true, false); //這裏省略的部分代碼 //若是是Result,則直接轉向 if (mapping.getResult() != null) { Result result = mapping.getResult(); result.execute(proxy.getInvocation()); } else { proxy.execute();//執行Action } //這裏省略的部分代碼 }在下一篇文章會詳細說下ActionProxy和ActionInvocation。
這個方法就不詳細闡述了,源碼中的註釋已經很清楚了。 code
//clean up ObjectFactory //clean up Dispatcher itself for this thread //clean up DispatcherListeners //clean up all interceptors by calling their destroy() method //cleanup action context //clean up configuration