Struts2源码阅读之Dispatcher

本文深入剖析Struts2的核心组件Dispatcher的工作原理,包括其初始化流程、如何服务Action及清理过程。详细介绍了Dispatcher如何通过ConfigurationProvider加载配置文件并注册配置项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    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

转载于:https://my.oschina.net/mlongbo/blog/90091

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值