zoukankan      html  css  js  c++  java
  • Tomcat容器运行struts2+spring+mybatis架构的java web应用程序简单分析

    1、具体的环境为

    MyEclipse 8.5以及自带的tomcat

    spring3.0.5

    struts2.3.15.1

    mybatis3.0.5

    2、想弄明白的一些问题

    tomcat集成spring,那么spring是如何启动的?

    spring是如何读取配置文件的?

    spring是如何处理依赖关系的?

    应该说所有的bean都是spring实例化的,那么Action的实例是如何产生的?

    3、spring是如何启动的?

    了解了tomcat的启动过程(容器engine-host-context-wrapper一级一级启动,并且通过事件如ContextConfig等来读取各自应用的web.xml来初始化context),
    读了web.xml中的配置,spring也是通过事件来启动的,配置如下:

        <listener>
            <listener-class>
                org.springframework.web.util.Log4jConfigListener
            </listener-class>
        </listener>    
        
         <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
            </listener-class>
        </listener>

    注意的是,如果配置了Log4jConfigListener,则Log4jConfigListener的配置要先于ContextLoaderListener的配置(spring3.0.5源码注释得知)。

    4、spring启动后做了哪些事情?

    通过debug3.0.5的源码,spring解析所有的配置文件,配置文件路径可以如下配置:

        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:applicationContext*.xml</param-value>
        </context-param>

    然后,spring可以得到该应用共有多少个bean(如现在的项目,大概是200+个)

    这里,spring还会解析所有的*Sql.xml文件,得到所有的statement mapper
    .
    .
    .

    5、Action的实例是如何产生的?也是spring进行管理的吗?

    首先Action的实例化不是由spring管理的,因为默认spring产生的实例都是单例的,而Action为了避免多线程产生的不一致,是多例的。

    Action的作用是通过Filter机制来实现的:

        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>
                org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
            </filter-class>
        </filter>
        <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    这样所有的请求都会经过这个filter,而如果url是以.action(可在struts.properties中配置)结尾的,则会根据struts*.xml文件中的映射关系new出一个Action
    进行处理。

    5.1、

    首先web application启动时,在初始化spring后,会调用org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(FilterConfig filterConfig) throws ServletException方法,在Dispatcher.java的init方法中会读取解析struts*xml配置文件:

       /**
         * Load configurations, including both XML and zero-configuration strategies,
         * and update optional settings, including whether to reload configurations and resource files.
         */
        public void init() {
    
            if (configurationManager == null) {
                configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
            }
    
            try {
                init_FileManager();
                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_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);
            }
        }

    然后通过*Provider的register方法来读取各种配置文件(struts默认的以及自己配置的)
    如DefaultPropertiesProvider、XmlConfigrationProvider...

    注意:和spring有一点不同,struts的ConfigurationManager只会解析struts.xml这个文件(可以配置指定特定名称),如果我们建立了另外的xml配置文件,
    如struts-wms.xml,则需要在struts.xml中如下配置,
    <include file="struts-wms.xml"></include>
    配置文件的包含关系可以多层级的。

    5.2、

    在每次请求到来的时候,会调用void org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException这个方法,

            //首先,判断这个请求url是不是在struts2处理的排除范围内,如果是,则继续调用其他filter进行处理
                if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
                    chain.doFilter(request, response);
                } else {
                    request = prepare.wrapRequest(request);
            //根据请求url得到对应的action mapping
                    ActionMapping mapping = prepare.findActionMapping(request, response, true);
            //如果action mapping为空,则调用其他的filter进行处理
                    if (mapping == null) {
                        boolean handled = execute.executeStaticResourceRequest(request, response);
                        if (!handled) {
                            chain.doFilter(request, response);
                        }
                    } else {
                //否则调用action mapping对应的Action进行处理
                        execute.executeAction(request, response, mapping);
                    }
                }

    一点猜想:
    在调用完所有的filter之后,如果是由对应Action处理,则由Action处理完成后,通过向response中设值,交由tomcat处理后返回客户端;
    如果不是,如图片/js等静态资源,应该是有Tomcat分派的处理线程调用默认的DefaultServlet返回相应资源。
    结论是,不论是不是由Action处理,还是tomcat内部直接处理,只要通过封装了request和response,最后就一定可以通过tomcat的处理返回结果到客户端。。

    6、Action中使用到的*Service可以通过@Autowired自动注入,这是通过什么样的机制??

    ActionContext会new出对应的Action,那么Action中的字段如*Service是通过什么样的机制注入的?猜想是通过某个Interceptor。
    但是,通过在*.java文件中搜索"Autowired.class",结果为0,意识到*Service的注入可能不是通过Interceptor。


    在通过debug查看StrutsActionProxy中的DefaultActionInvocation字段中的*Action示例,发现*Service都是实例化过后的。

    现在重点是弄明白StrutsActionProxy是如何实例化的?
    通过这个类Object com.opensymphony.xwork2.spring.SpringObjectFactory.buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception
    来实例化Action并注入*Service的,其中会得到spring的BeanFactory的实现进而得到所有的由spring管理的*Service。。

  • 相关阅读:
    linux指令大全
    strcpy.strcmp.strlen.strcat函数的实现
    推箱子
    头文件string.h里的函数
    SVN 版本控制工具
    Nodejs 学习
    JavaScript基础知识复习
    CSS3 学习小结
    JSP中 JSTL
    JSP中的EL语言
  • 原文地址:https://www.cnblogs.com/wenwujuncheng/p/3586359.html
Copyright © 2011-2022 走看看