您的位置:首页 > 编程语言 > Java开发

Struts2源码阅读之Dispatcher

2012-11-18 12:23 337 查看
Dispatcher是Struts2的核心分发器,就好比SpringMVC的DispatcherServlet,它是完成url解析转向,读取对应Action的地方,相当于一个路由。

先看一段代码:

private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();
可以看到,Dispatcher也是使用ThreadLocal模式。在Struts2中大量使用了ThreadLocal模式,比如上次说到的ActionContext。

创建Dispatcher:

public Dispatcher(ServletContext servletContext, Map<String, String> initParams) {
this.servletContext = servletContext;
this.initParams = initParams;
}

initParams配置在web.xml中的param参数.

接下来,主要会阐述init,serviceAction,cleanup这三个方法。

1.init

init方法的主要工作是初始化配置文件,它会分七步载入各种配置文件,都是通过ConfigurationProvider接口进行的,这个接口提供init(),destroy(),register()等方法.。将各种ConfigurationProvider初始化之后将实例添加到ConfigurationManager的List里面,最后通过循环调用List里的这些destroy(),register()等方法实现对配置文件的属性进行注册和销毁等功能。

第一步:

init_DefaultProperties(); // [1]

private void init_DefaultProperties() {
configurationManager.addContainerProvider(new DefaultPropertiesProvider());
}

DefaultPropertiesProvider:读取properties信息,默认是default.properties

第二步:

init_TraditionalXmlConfigurations(); // [2]读取xml配置文件
这里面会涉及到两个类XmlConfigurationProvider,StrutsXmlConfigurationProvider,后者是前者的子类。XmlConfigurationProvider负责解析xwork.xml,其它xml文件由StrutsXmlConfigurationProvider解析。

第三步:

init_LegacyStrutsProperties();
LegacyPropertiesConfigurationProvider负责读取用户自定义的struts.properties文件信息。该类继承自DefaultPropertiesProvider。

第五步:

源码注释直接第五步,我一直没找到第四步在哪,还请大侠们指教。

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

这个方法就不详细阐述了,源码中的注释已经很清楚了。

//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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: