刨根问底-struts-初始化各种配置加载器

刨根问底-struts-初始化各种配置加载器_第1张图片

项目中配置struts2在web.xml

<filter>
<filter-name>struts</filter-name> 
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter> 

FilterDispatcher是struts2的核心控制器,每个请求都会进入FilterDispatcher对象的doFilter()方法。然后再struts.xml文件中根据action的name属性进行匹配,找到要执行的action类和方法,执行完方法返回结果。

1、首先分析FilterDispatcher加载struts的各种配置文件。

首先看看init()方法:

  public void init(FilterConfig filterConfig) throws ServletException {
        try {
            this.filterConfig = filterConfig;

            initLogging();

            dispatcher = createDispatcher(filterConfig);
            dispatcher.init();
            dispatcher.getContainer().inject(this);

            staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
        } finally {
            ActionContext.setContext(null);
        }
    }

注释:(1)iniggtLoing()初始化log日志

(2)createDispatcher(filterConfig)创建dispatcher,并且通过init()初始化相应的信息

2、createDispatcher(filterConfig)方法代码:

 protected Dispatcher createDispatcher(FilterConfig filterConfig) {
        Map<String, String> params = new HashMap<String, String>();
        for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
            String name = (String) e.nextElement();
            String value = filterConfig.getInitParameter(name);
            params.put(name, value);
        }
        return createDispatcher(filterConfig.getServletContext(), params);
    }

注释:主要是把web.xml中init-param的标签数据保存到类型map的params中,然后继续调用createDispatcher(filterConfig.getServletContext(), params)创建dispatcher

3、createDispatcher(filterConfig.getServletContext(), params)的源码:

 protected Dispatcher createDispatcher(ServletContext ctx, Map<String, String> params) {
        return new Dispatcher(ctx, params);
    }

注释:很简单,就是new Dispatcher对象。Dispather被称之为struts2的核心分发器,主要是基于在整个struts2框架中的特殊地位。

4、Dispatcher的构造函数:

 public Dispatcher(ServletContext servletContext, Map<String, String> initParams) {
        this.servletContext = servletContext;
        this.initParams = initParams;
    }
5、创建好d ispatcher对象,然后回到 步骤1中org.apache.struts2.dispatcher.FilterDispatcher中init()方法,然后会调用dispatcher.init(), init()方法是用来Load用户配置文件,资源文件以及默认的配置文件.

 public void init() {

    	if (configurationManager == null) {
    		configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);////设置ConfigurationManager的defaultFrameworkBeanName.       //这里DEFAULT_BEAN_NAME为struts,这是xwork框架的内容,Framework可以是xwork,struts,webwork等  }

        try {
            init_DefaultProperties(); // [1]//读取properties信息,默认的default.properties                     init_TraditionalXmlConfigurations(); // [2]读取xml配置文件 
init_LegacyStrutsProperties(); // [3]读取用户自定义的struts.properties   
init_CustomConfigurationProviders(); // [5]自定义的configProviders 
init_FilterInitParameters() ; // [6]载入FilterDispatcher传进来的initParams     
init_AliasStandardObjects() ; // [7]将配置文件中的bean与具体的类映射     //构建一个用于依赖注射的Container对象, 在这里面会循环调用上面七个ConfigurationProvider的register方法其中的重点就是DefaultConfiguration的#reload()方法  
 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);
        }
    }
注释:(1)通过createConfigurationManager创建配置控制器, createConfigurationManager方法就是简单new ConfigurationManager(name)对象。


(2)init_DefaultProperties() 读取properties信息,默认的default.properties,详细分析请看步骤5.1

(3)init_TraditionalXmlConfigurations读取xml配置文件,struts-default.xml,struts-plugin.xml,struts.xml,请看步骤5.2

(4)init_LegacyStrutsProperties()读取用户自定义struts.properties

(5)init_CustomConfigurationProviders()初始化自定义的配置加载器,请看步骤5.3

(6)init_FilterInitParameters()初始化由wen.xml穿件来的运行参数  ,请看步骤5.4

(7)init_AliasStandardObjects()将配置文件中的bean与具体的类映射  ,初始化默认容器内置对象,后面会详细的解释。  

到这里初始化各种形式的配置加载方法,这里只是定义了配置和加载的方法,并没有真正执行加载配置的逻辑

下面这几步初始化容器,这里包含两个不同的过程:(1)对所有定义的配置加载方式的逻辑执行,将它们初始化到configuration中(2)初始化struts2中的对象管理器 

            Container container = init_PreloadConfiguration();
            container.inject(this);对container进行依赖注入,所有在struts2中定义的对象的生命周期在此操作后都被纳入容器管理

            init_CheckConfigurationReloading(container);
            init_CheckWebLogicWorkaround(container);

额外初始化,检查是否支持reloading加载和对weblogic服务器的特殊处理
刨根问底-struts-初始化各种配置加载器_第2张图片

5.1init_DefaultProperties() 代码:

 private void init_DefaultProperties() {
        configurationManager.addContainerProvider(new DefaultPropertiesProvider());
    }
5.1.1DefaultPropertiesProvider().java代码:

public class DefaultPropertiesProvider extends LegacyPropertiesConfigurationProvider {

    public void destroy() {
    }

    public void init(Configuration configuration) throws ConfigurationException {
    }

    public void register(ContainerBuilder builder, LocatableProperties props)
            throws ConfigurationException {
        
        Settings defaultSettings = null;
        try {
            defaultSettings = new PropertiesSettings("org/apache/struts2/default");
        } catch (Exception e) {
            throw new ConfigurationException("Could not find or error in org/apache/struts2/default.properties", e);
        }
        
        loadSettings(props, defaultSettings);
    }

}
注释:初始化struts2默认的properties文件,该文件是org/apache/struts2/目录下的default.properties文件

5.2init_TraditionalXmlConfigurations()加载xml配置

private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";

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.addContainerProvider(createXmlConfigurationProvider(file, false));
                } else {
                    configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
                }
            } else {
                throw new IllegalArgumentException("Invalid configuration file name");
            }
        }
    }
protected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) {
        return new StrutsXmlConfigurationProvider(filename, errorIfMissing, ctx);
    }

5.3init_CustomConfigurationProviders()--初始化用户自定义的配置加载器,代码:
private void init_CustomConfigurationProviders() {
        String configProvs = initParams.get("configProviders");
        if (configProvs != null) {
            String[] classes = configProvs.split("\\s*[,]\\s*");
            for (String cname : classes) {
                try {
                    Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
                    ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();
                    configurationManager.addContainerProvider(prov);
                } catch (InstantiationException e) {
                    throw new ConfigurationException("Unable to instantiate provider: "+cname, e);
                } catch (IllegalAccessException e) {
                    throw new ConfigurationException("Unable to access provider: "+cname, e);
                } catch (ClassNotFoundException e) {
                    throw new ConfigurationException("Unable to locate provider class: "+cname, e);
                }
            }
        }
    }
5.4init_FilterInitParameters()--初始化由web.xml传入的运行参数,代码:

 private void init_FilterInitParameters() {
        configurationManager.addContainerProvider(new ConfigurationProvider() {
            public void destroy() {
            }

            public void init(Configuration configuration) throws ConfigurationException {
            }

            public void loadPackages() throws ConfigurationException {
            }

            public boolean needsReload() {
                return false;
            }

            public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
                props.putAll(initParams);
            }
        });
    }







你可能感兴趣的:(刨根问底-struts-初始化各种配置加载器)