`
韩悠悠
  • 浏览: 839769 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

struts源码之三

 
阅读更多

在init初始化方法中我们看到这样一句

 InitOperations init = new InitOperations();

这个类没什么作用,就是一个辅助类,来完成初始化的操作。

继续往下看

FilterHostConfig config = new FilterHostConfig(filterConfig);
            init.initLogging(config);
            Dispatcher dispatcher = init.initDispatcher(config);
            init.initStaticContentLoader(config, dispatcher);

 创建了FilterHostConfig,这个类也没什么作用就是包装FilterConfig

用官方的原话说

Host configuration that wraps FilterConfig

通过传入一个filterConfig完成该类的初始化。

public class FilterHostConfig implements HostConfig {

    private FilterConfig config;

    public FilterHostConfig(FilterConfig config) {
        this.config = config;
    }
    public String getInitParameter(String key) {
        return config.getInitParameter(key);
    }

    public Iterator<String> getInitParameterNames() {
        return MakeIterator.convert(config.getInitParameterNames());
    }

    public ServletContext getServletContext() {
        return config.getServletContext();
    }
}

 

该类处理完成,真正的初始化才开始,通过初始化辅助类InitOperations来完成初始化。

首先初始化日志信息

 init.initLogging(config);

 public void initLogging( HostConfig filterConfig ) {
        String factoryName = filterConfig.getInitParameter("loggerFactory");
        if (factoryName != null) {
            try {
                Class cls = ClassLoaderUtil.loadClass(factoryName, this.getClass());
                LoggerFactory fac = (LoggerFactory) cls.newInstance();
                LoggerFactory.setLoggerFactory(fac);
            } catch ( InstantiationException e ) {
                System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
                e.printStackTrace();
            } catch ( IllegalAccessException e ) {
                System.err.println("Unable to access logger factory: " + factoryName + ", using default");
                e.printStackTrace();
            } catch ( ClassNotFoundException e ) {
                System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
                e.printStackTrace();
            }
        }
    }

 

通过代码我们可以清晰的看到factoryName一定是空的,因为我们压根就没在web.xml中配置factoryName.

所以里面的方法一定不执行。

直接返回。

 

接下来进入到Dispatcher dispatcher = init.initDispatcher(config);

初始化并创建Dispatcher

Dispatcher是struts2的核心类,完成大部分任务调度,所有的请求共享这一实例。

 

 public Dispatcher initDispatcher( HostConfig filterConfig ) {
        Dispatcher dispatcher = createDispatcher(filterConfig);
        dispatcher.init();
        return dispatcher;
    }

 

通过代码也可以看到Dispatcher是先创建,然后初始化。

它的创建很简单

private Dispatcher createDispatcher( HostConfig filterConfig ) {
        Map<String, String> params = new HashMap<String, String>();
        for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) {
            String name = (String) e.next();
            String value = filterConfig.getInitParameter(name);
            params.put(name, value);
        }
        return new Dispatcher(filterConfig.getServletContext(), params);
    }

 

把web.xml 中所有的配置信息取出来,放入一个hashmap中,然后存入Dispatcher中。就这样,完了

然后进入初始化,这个有点点复杂

 

public void init() {

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

        try {
            init_DefaultProperties(); // [1]
            init_TraditionalXmlConfigurations(); // [2]
            init_LegacyStrutsProperties(); // [3]
            init_CustomConfigurationProviders(); // [5]
            init_FilterInitParameters() ; // [6]
            init_AliasStandardObjects() ; // [7]

            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);
        }
    }

 

通过代码可以看到,初始化做了很多事,首先是创建configurationManager

protected ConfigurationManager createConfigurationManager(String name) {
        return new ConfigurationManager(name);
    }

 

直接new一个configurationManager出来。默认的名称就是struts

 

初始化属性读取的类

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

 

以下所有的都一样,将所有的provider初始化,所有的Provider实现类都实现了ConfigurationProvider这个接口。

ConfigurationProvider这个接口又干嘛呢?

public interface ConfigurationProvider extends ContainerProvider, PackageProvider {
}

 

通过代码可以看到核心不在这里,在ContainerProvider和PackageProvider,

这里需要说的是ContainerProvider是容器的初始化,PackageProvider是包的初始化.

什么是容器呢?在struts2中constants/properties配置的信息就是容器的相关信息

PackageProvider就是包的信息,比如我们的struts.xml

 

回到初始化代码中,DefaultPropertiesProvider就是提供了一个读取默认的struts.properties的实现类。

好了,继续初始化操作。

初始化init_TraditionalXmlConfigurations

 

 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");
            }
        }
    }

 这里提供了俩种初始化配置文件的方法,当然他也提供了选择String configPaths = initParams.get("config");

但是我们在web.xml中没配置,所有默认的一定是struts,而不是xwork

protected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) {
        return new StrutsXmlConfigurationProvider(filename, errorIfMissing, ctx);
    }

 

configPaths = DEFAULT_CONFIGURATION_PATHS;

这里我们可以得到证明

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

 

继续往里面看,我们看到

 public StrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) {
        super(filename, errorIfMissing);
        this.servletContext = ctx;
        this.filename = filename;
        reloadKey = "configurationReload-"+filename;
        Map<String,String> dtdMappings = new HashMap<String,String>(getDtdMappings());
        dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.0//EN", "struts-2.0.dtd");
        dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.1//EN", "struts-2.1.dtd");
        dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN", "struts-2.1.7.dtd");
        dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.3//EN", "struts-2.3.dtd");
        setDtdMappings(dtdMappings);
        File file = new File(filename);
        if (file.getParent() != null) {
            this.baseDir = file.getParentFile();
        }
    }

 加入了struts配置文件的验证dtd,在后续会讲

 

完成了struts配置文件的初始化,继续初始化

init_LegacyStrutsProperties

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

 

LegacyPropertiesConfigurationProvider这个初始化又干嘛呢?这个初始化主要完成除去上面初始化剩下的其他配置信息想初始化。

init_CustomConfigurationProviders();这个初始化很关键

以上的初始化都说初始化struts框架的配置信息,而这个初始化就是初始化我们在开发中写的配置文件

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 = ClassLoaderUtil.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);
                }
            }
        }
    }

 

通过代码可以看到,通过类加载器加载上来,然后放入configurationManager中。

 

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

 

 

这个初始化是初始化扩展框架的插件信息。

 

然后初始化一个容器

 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);

        return container;
    }

 

struts2的容器用来实现依赖注入和控制反转,定义如下

public interface Container extends Serializable {

  /**
   * Default dependency name.
   */
  String DEFAULT_NAME = "default";

  /**
   * Injects dependencies into the fields and methods of an existing object.
   */
  void inject(Object o);

  /**
   * Creates and injects a new instance of type {@code implementation}.
   */
  <T> T inject(Class<T> implementation);

  /**
   * Gets an instance of the given dependency which was declared in
   * {@link com.opensymphony.xwork2.inject.ContainerBuilder}.
   */
  <T> T getInstance(Class<T> type, String name);

  /**
   * Convenience method.&nbsp;Equivalent to {@code getInstance(type,
   * DEFAULT_NAME)}.
   */
  <T> T getInstance(Class<T> type);
  
  /**
   * Gets a set of all registered names for the given type
   * @param type The instance type
   * @return A set of registered names
   */
  Set<String> getInstanceNames(Class<?> type);

  /**
   * Sets the scope strategy for the current thread.
   */
  void setScopeStrategy(Scope.Strategy scopeStrategy);

  /**
   * Removes the scope strategy for the current thread.
   */
  void removeScopeStrategy();
}

 

 

未完待续

分享到:
评论

相关推荐

    struts2.1.8 struts2源码 Eclipse关联这个可以

    在Eclipse中关联Struts2.1.8源码,可以帮助开发者更好地理解和调试代码。步骤包括: - 下载Struts2.1.8的源码包。 - 在Eclipse中,右键点击项目,选择"Build Path" -&gt; "Configure Build Path" -&gt; "Libraries" -&gt; ...

    struts框架的源码包

    struts源码包,解压后会有一个src文件夹,此文件夹下的就是struts的源码。

    孙卫琴struts源码.part1.rar

    孙卫琴 struts 源码 孙卫琴 struts 源码 孙卫琴 struts 源码

    struts2源码最新

    3. **插件体系**:Struts2支持丰富的插件,如Struts2-convention插件可以实现自动映射Action和方法,Struts2-dojo-plugin则提供了与Dojo库的集成,便于创建富客户端应用。 4. **OGNL(Object-Graph Navigation ...

    struts源码struts源码struts源码

    通过深入研究Struts源码,我们可以了解到框架如何处理请求、执行业务逻辑以及如何将数据呈现给用户。这对于提升Java Web开发技能,理解MVC模式,以及进行性能优化都有着极大的帮助。同时,熟悉源码也有助于开发者更...

    struts2 项目源码

    本项目源码提供了一个基础的Struts2应用程序实例,对于初学者来说,这是一个很好的学习资源,可以深入理解Struts2的工作原理和架构。 Struts2的核心组件包括: 1. **Action类**:Action类是业务逻辑的载体,它是...

    struts2 源码解读

    这篇博文“Struts2源码解读”深入剖析了Struts2的核心机制,帮助开发者更好地理解和利用这个框架。源码分析是提升编程技能和解决问题的关键,特别是对于复杂的框架如Struts2,理解其内部工作原理能够帮助我们优化...

    struts2 源码分析

    Struts2 源码分析 Struts2 是一个基于MVC 模式的Web 应用程序框架,它的源码分析可以帮助我们更好地理解框架的内部机制和工作流程。下面是Struts2 源码分析的相关知识点: 1. Struts2 架构图 Struts2 的架构图...

    struts2框架源码

    深入理解Struts2的源码对于提升Java Web开发技能,尤其是在面试中讨论底层实现时,具有非常重要的价值。 首先,我们来看看Struts2的核心组件和设计理念: 1. **Action**:在Struts2中,Action类是业务逻辑处理的...

    Struts2源码阅读

    通过阅读Struts2的源码,我们可以深入了解框架如何处理请求、如何调度Action以及如何应用拦截器来扩展功能。这有助于开发者更好地定制和优化他们的应用程序,提高代码质量和性能。在实际开发中,对源码的理解能帮助...

    struts2 源码

    深入学习Struts2的源码,有助于理解其运行机制,从而更好地优化代码、调试问题,甚至开发自己的扩展。对于Java Web开发者来说,掌握Struts2的基本原理和使用技巧,能够显著提高开发效率和应用质量。

    孙卫琴struts源码.part3.rar

    孙卫琴 struts 源码 孙卫琴 struts 源码 孙卫琴 struts 源码 103m

    struts-1.3.9 源码

    3. **org.apache.struts.util**:包含了一些工具类和辅助类,比如国际化(`MessageResources`)、请求处理(`RequestUtils`)等。 4. **org.apache.struts.taglib**和**org.apache.struts.taglib.html**: 这些是Struts...

    struts2学习 源码

    3. **拦截器(Interceptors)**:拦截器是Struts2的一大亮点,它们在Action调用前后执行,可以实现如日志、事务管理、权限控制等功能,提高了代码的可复用性。 4. **结果类型(Result Types)**:框架支持多种结果...

    Struts jar包和源码包(含3个版本)

    本资源包含了Struts的三个不同版本的jar包和源码包:struts-2.3.37-all.zip、struts-2.5.20-all.zip以及struts-1.3.10-all.zip,分别对应了Struts 2的2.3.37版本、2.5.20版本和Struts 1的1.3.10版本。下面将详细讲解...

    struts-1.2.9源码

    通过对Struts 1.2.9源码的深入学习,开发者可以了解Web应用的典型开发流程,掌握如何有效地组织和管理复杂的业务逻辑,以及如何优雅地处理用户交互。虽然Struts 1已逐渐被Struts 2和Spring MVC等更新框架替代,但它...

    Struts2源码分析

    在深入理解Struts2的工作原理时,源码分析是必不可少的步骤。Struts2的核心设计理念和设计模式相比Struts1.x有了显著的变化,这使得它成为一个独立且成熟的框架。 首先,Struts2的架构基于WebWork的核心,这意味着...

    Struts 2的源码

    在深入理解Struts 2的源码之前,我们需要先了解其核心概念和组件。 1. **Action类与ActionMapping** Struts 2的核心是Action类,它是业务逻辑处理的中心。每个Action类对应一个用户请求,处理后返回一个Result。...

    STRUTS2源码解析

    STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析STRUTS2源码解析...

    struts2中的OGNL的源码

    通过深入学习OGNL的源码,开发者可以更好地定制和优化Struts2应用,提升性能,增强安全性,并能解决遇到的特定问题。这是一项值得投入时间和精力的任务,特别是对于那些希望在Web开发领域有深入理解的人来说。

Global site tag (gtag.js) - Google Analytics