`
zddava
  • 浏览: 243690 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Struts2的配置文件读取(一)

阅读更多
struts2利用FilterDispatcher来拦截请求,然后进行请求的分发,在FilterDispatcher的#init()方法里,实现了配置文件的读入。

代码如下:

    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        
        dispatcher = createDispatcher(filterConfig);
        dispatcher.init();
        
        String param = filterConfig.getInitParameter("packages");
        String packages = "org.apache.struts2.static template org.apache.struts2.interceptor.debugging";
        if (param != null) {
            packages = param + " " + packages;
        }
        this.pathPrefixes = parse(packages);
    }


-------------------------------------------------------------------------------------------------

先调用#createDispatcher()来创建一个Dispatcher对象,并将FilterConfig中的属性读出,代码如下:

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


在#createDispatcher()中,将Filter的配置中的所有属性都写入一个HashMap并作为参数传递给Dispatcher的构造函数。

-------------------------------------------------------------------------------------------------

再回到#init()函数中,创建完Dispatcher对象后,紧接着调用Dispatcher的#init()方法。代码如下:

    public void init() {

        if (configurationManager == null) {
            configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
        }

        init_DefaultProperties(); // [1]
        init_TraditionalXmlConfigurations(); // [2]
        init_LegacyStrutsProperties(); // [3]
        init_ZeroConfiguration(); // [4]
        init_CustomConfigurationProviders(); // [5]
        init_MethodConfigurationProvider();
        init_FilterInitParameters(); // [6]
        init_AliasStandardObjects(); // [7]

        Container container = init_PreloadConfiguration();
        init_CheckConfigurationReloading(container);
        init_CheckWebLogicWorkaround(container);

    }


首先实例化一个ConfigurationManager对象。

然后就是调用一系列的#init_*()方法了。

-------------------------------------------------------------------------------------------------

●第一个是

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


这个方法中是将一个DefaultPropertiesProvider对象追加到ConfigurationManager对象内部的ConfigurationProvider队列中。
DefaultPropertiesProvider的#register()方法可以载入org/apache/struts2/default.properties中定义的属性。

-------------------------------------------------------------------------------------------------

●第二个是

    private void init_TraditionalXmlConfigurations() {
        String configPaths = initParams.get("config");
        if (configPaths == null) {
            configPaths = DEFAULT_CONFIGURATION_PATHS;
        }
        String[] files = configPaths.split("[url=file://\\s*[,]\\s]\\s*[,]\\s[/url]*");
        for (String file : files) {
            if (file.endsWith(".xml")) {
                if ("xwork.xml".equals(file)) {
                    configurationManager.addConfigurationProvider(new XmlConfigurationProvider(
                            file, false));
                } else {
                    configurationManager
                            .addConfigurationProvider(new StrutsXmlConfigurationProvider(file,
                                    false, servletContext));
                }
            } else {
                throw new IllegalArgumentException("Invalid configuration file name");
            }
        }
    }


这里负责载入的是FilterDispatcher的配置中所定义的config属性。
如果用户没有定义config属性,struts默认会载入DEFAULT_CONFIGURATION_PATHS这个值所代表的xml文件。
它的值为"struts-default.xml,struts-plugin.xml,struts.xml"。也就是说框架默认会载入这三个项目xml文件。

下一步框架会逐个判断每个config属性中定义的文件。如果文件名为"xwork.xml",框架会用XmlConfigurationProvider类去处理,反之则用StrutsXmlConfigurationProvider类去处理。

-------------------------------------------------------------------------------------------------

●第三个是

    private void init_LegacyStrutsProperties() {
        configurationManager.addConfigurationProvider(new LegacyPropertiesConfigurationProvider());
    }


向ConfigurationManager加入了一个LegacyPropertiesConfigurationProvider。

-------------------------------------------------------------------------------------------------

●第四个是

    private void init_ZeroConfiguration() {
        String packages = initParams.get("actionPackages");
        if (packages != null) {
            String[] names = packages.split("[url=file://\\s*[,]\\s]\\s*[,]\\s[/url]*");
            // Initialize the classloader scanner with the configured packages
            if (names.length > 0) {
                ClasspathConfigurationProvider provider = new ClasspathConfigurationProvider(names);
                provider.setPageLocator(new ServletContextPageLocator(servletContext));
                configurationManager.addConfigurationProvider(provider);
            }
        }
    }


这次处理的是FilterDispatcher的配置中所定义的actionPackages属性。传说中的Struts 2 零配置。
该参数的值是一个以英文逗号(,)隔开的字符串,每个字符串都是一个包空间,Struts 2框架将扫描这些包空间下的Action类。

-------------------------------------------------------------------------------------------------

●第五个是

    private void init_CustomConfigurationProviders() {
        String configProvs = initParams.get("configProviders");
        if (configProvs != null) {
            String[] classes = configProvs.split("[url=file://\\s*[,]\\s]\\s*[,]\\s[/url]*");
            for (String cname : classes) {
                try {
                    Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
                    ConfigurationProvider prov = (ConfigurationProvider) cls.newInstance();
                    configurationManager.addConfigurationProvider(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);
                }
            }
        }
    }


此方法处理的是FilterDispatcher的配置中所定义的configProviders属性。负责载入用户自定义的ConfigurationProvider。

-------------------------------------------------------------------------------------------------

●第六个是

    private void init_FilterInitParameters() {
        configurationManager.addConfigurationProvider(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);
            }
        });
    }


此方法用来处理FilterDispatcher的配置中所定义的所有属性。

-------------------------------------------------------------------------------------------------

●第七个是

	private void init_AliasStandardObjects() {
		configurationManager.addConfigurationProvider(new BeanSelectionProvider());
	}


-------------------------------------------------------------------------------------------------

执行完七个init_*方法后,Dispatcher的#init()会接着调用#init_PreloadConfiguration(),构建一个用于依赖注射的Container对象。

    private Container init_PreloadConfiguration() {
        Configuration config = configurationManager.getConfiguration();
        Container container = config.getContainer();

        boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class,
                StrutsConstants.STRUTS_I18N_RELOAD));
        LocalizedTextUtil.setReloadBundles(reloadi18n);

        ObjectTypeDeterminer objectTypeDeterminer = container
                .getInstance(ObjectTypeDeterminer.class);
        ObjectTypeDeterminerFactory.setInstance(objectTypeDeterminer);

        return container;
    }


此方法首先获取到ConfigurationManager中的Configuration对象,在#getConfiguration()内部,调用上边6步添加到ConfigurationManager的ConfigurationProviders的#register()方法。

    public synchronized Configuration getConfiguration() {
        if (configuration == null) {
            setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
            try {
              configuration.reload(getConfigurationProviders());
            } catch (ConfigurationException e) {
              setConfiguration(null);
              throw e;
            }
        } else {
            conditionalReload();
        }

        return configuration;
    }


其中的重点就是DefaultConfiguration的#reload()方法。

    public synchronized void reload(List providers) throws ConfigurationException {
        packageContexts.clear();
        loadedFileNames.clear();

        ContainerProperties props = new ContainerProperties();
        ContainerBuilder builder = new ContainerBuilder();
        for (ConfigurationProvider configurationProvider : providers)
        {
            configurationProvider.init(this);
            configurationProvider.register(builder, props);
        }
        props.setConstants(builder);
        
        builder.factory(Configuration.class, new Factory() {
            public Configuration create(Context context) throws Exception {
              return DefaultConfiguration.this;
            }
        });
        
        try {
            // Set the object factory for the purposes of factory creation
            ObjectFactory.setObjectFactory(new ObjectFactory());
            
            container = builder.create(false);
            objectFactory = container.getInstance(ObjectFactory.class);
            ObjectFactory.setObjectFactory(objectFactory);
            
            for (ConfigurationProvider configurationProvider : providers)
            {
              container.inject(configurationProvider);
              configurationProvider.loadPackages();
            }
    
            rebuildRuntimeConfiguration();
        } finally {
            ObjectFactory.setObjectFactory(null);
        }
    }
分享到:
评论

相关推荐

    struts2配置文件加载顺序

    1. **struts-default.xml**:这是Struts2的核心配置文件,位于`struts2-core.jar`库的`/org/apache/struts2/defaults`包内。它包含了框架的基本设置,如拦截器栈、默认Action配置等。 2. **struts-plugin.xml**:这...

    struts2配置文件传值中文乱码

    本文将围绕“Struts2配置文件传值中文乱码”这一主题,深入探讨其成因、解决方案以及相关的配置细节,旨在帮助开发者有效解决中文乱码问题,提升用户体验。 ### Struts2框架简介 Struts2是Apache组织下的一个开源...

    struts2 配置文件

    ### Struts2 配置文件详解 #### 一、引言 在Struts2框架的应用开发过程中,配置文件起到了至关重要的作用。Struts2主要依赖于两种基于XML的配置文件:`web.xml` 和 `struts-config.xml`(通常命名为 `struts.xml`)...

    struts2配置文件改变位置问题

    确保配置文件的路径相对于`WEB-INF/classes`是可访问的,这样才能使Struts2成功读取并解析配置,从而正常运行应用程序。 总结一下,当遇到Struts2配置文件位置更改问题时,应遵循以下步骤: 1. 确保新的`struts....

    知识共享-struts1.2配置文件详解(雷惊风).

    - 这是Struts配置文件的根元素,其配置类为org.apache.struts.config.ModuleConfig。该元素下有8个子元素,每个都扮演着不同的角色,如数据源配置、全局异常处理、全局转发等。 #### 2. **Data-Sources元素** - `...

    struts2实现文件下载功能

    在Struts2的配置文件(struts.xml)中添加相应的配置。 3. **设置Content-Type和Content-Disposition**: - 在Action类中,使用`ValueStack`或`ActionContext`来设置HTTP响应的`Content-Type`和`Content-...

    struts2文件上传例子.rar

    文件上传需要配置Struts2的配置文件,通常为`struts.xml`。在这个配置文件中,需要定义一个或多个与Action类对应的Action配置,设置`result`来指定成功后跳转的页面。同时,我们还需要配置`struts.multipart.saveDir...

    Struts2文件流方式导出下载excel、Txt、image图片

    2. **配置struts.xml**:在Struts2的配置文件中,我们需要为这个Action添加相应的配置,指定返回的`StreamingResult`结果类型和对应的视图。 ```xml <param name="contentType">application/octet-stream ...

    struts2实现多文件上传下载

    2.能够对上传路径进行配置文件指定(upload.properties),使用了一些类似单例模式的静态代码块 3.Struts2进行下载处理,能对上传的所有文件进行下载(多个) 4.文件保存的名称UUID生成,不过显示并下载的名称都是原...

    struts2框架下的文件上传

    然后,在struts.xml配置文件中启用`struts.multipart.parser`参数为`copy`,这样Struts2会自动处理文件上传。 ```xml <constant name="struts.multipart.parser" value="copy"/> ``` 在Action类中,你可以这样...

    Struts2之struts2文件上传详解案例struts011

    接着,我们需要在Struts配置文件(struts.xml)中配置Action,确保它能够处理文件上传的请求。配置通常包括Action的名称、对应的类以及结果页面。例如: ```xml <result name="success">/success.jsp ...

    struts2上传文件进度条显示

    在`struts.xml`配置文件中添加以下配置: ```xml <constant name="struts.multipart.enabled" value="true"/> <constant name="struts.multipart.maxSize" value="20971520"/> <!-- 20MB --> ``` 这里我们启用了...

    struts2 properties配置详解

    自己学会的,保存的学习网页,给大家分享 struts2 国际化

    Struts配置文件使用及代码详解

    Struts2是一个强大的Java EE平台上的MVC框架,它的设计目标是简化Web应用程序的...以上便是Struts2配置文件的使用和代码详解,通过理解这一框架的工作原理和优势,开发者可以更加高效地利用Struts2来构建Web应用程序。

    struts2_uploadify带进度条的多文件上传下载

    3. 配置文件:如struts.xml,配置Struts2的动作映射和结果类型,确保上传请求能被正确路由到对应的Action。 4. Servlet或Filter:可能用于处理文件上传的细节,如设置最大文件大小限制、处理多部分请求等。 5. 下载...

    Struts配置文件详解

    #### 一、Struts配置文件的重要性与作用 Struts框架作为SSH(Struts+Spring+Hibernate)三大框架之一,在企业级Web应用开发中扮演着核心角色。Struts配置文件是Struts框架的灵魂所在,它不仅控制着框架的初始化流程...

    利用Java的Properties 类读取配置文件信息

    在Java编程中,读取配置文件是常见的任务,主要用于存储应用程序的设置或环境变量,以方便管理和维护。Java提供了一个内置的`java.util.Properties`类,用于处理`.properties`文件,这种格式通常用来存储键值对,即...

    Struts配置文件详解.pdf

    #### 一、Struts配置文件的重要性与作用 Struts框架作为Java Web开发领域中的一种流行MVC(Model-View-Controller)框架,它提供了一种结构化的方式来构建Web应用程序。在Struts框架中,`struts-config.xml`配置...

    struts2文件上传下载

    首先,你需要在项目的配置文件(如struts.xml)中启用文件上传的支持,并配置相应的拦截器。接着,在Action类中创建一个字段来接收上传的文件,Struts2会自动将文件内容绑定到这个字段上。 例如,你可以创建一个名...

Global site tag (gtag.js) - Google Analytics