Struts2源碼閱讀之Dispatcher

    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

1.init

    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方法進行註冊。

2.serviceAction

    直接貼代碼吧。 代理

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。

3.cleanup

    這個方法就不詳細闡述了,源碼中的註釋已經很清楚了。 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
相關文章
相關標籤/搜索