Struts2初始化流程及源码分析

1.1 Struts2初始化

在讲Struts2的初始化以前,应该为你们描述下Web应用中的过滤器Filter,这关系到咱们对核心过滤器FilterDispatcher的正确理解。java

Filter:一个filter是一个对象,为每一个请求资源(一个servlet或静态内容) ,或响应一个资源,或二者,用于执行过滤任务。过滤器执行过滤是在doFilter方法中。每一个过滤器方法访问一个FilterConfig对象从中获取初始化参数,filterConfig.getServletContext()能够得到ServletContext对象使用。过滤器的配置在Web应用程序的web.xml中。web

init():初始化过滤器,它的输入参数javax.servlet.FilterConfig的一个实例,能够在这里初始化过滤要使用到的FilterConfig。该方法由Web容器自动调用。apache

doFilter():进行具体的过滤操做,这个方法以javax.servlet.ServletRequest请求信息, javax.servlet.ServletResponse响应信息,javax.servlet.FilterChain过滤链。过滤链,在Web应用程序中全部的过滤器会构成一个链状,符合过滤条件的程序将会根据定义的顺序执行全部链中的过滤器。在这个方法中调用FilterChain的 doFilter(javax.servlet.ServletRequest, javax.servlet.SerletResponse)方法就能够传递到链中的下一个过滤器。数组

destory():销毁过滤器,能够在这里释放使用完的资源,例如设置过滤器中FilterConfig为null。ide

综上所述,在Web应用启动时,会默认初始化Filter,调用Filter的init(FilterConfig filterConfig)方法,当请求到来时,会按顺序执行web.xml中所配置Filter的doFilter(ServletRequest req, ServletResponse res, FilterChain chain)方法。源码分析

Struts2的核心过滤器FilterDispatcher实现的就是StrutsStatics, Filter接口,因此它本质就是一个过滤器,以下图所示:spa

image

因此Struts2的初始化工做在Web应用启动时,就能够经过FilterDispatcher核心过滤器init(FilterConfig filterConfig)方法来完成了。以下图所示:插件

clip_image004

FilterDispatcher.init(FilterConfig filterConfig)方法中主要工做分为:debug

a) 建立Dispatcher类对象,将FilterDispatcher配置的初始化参数传到该对象中;3d

b) 加载并解析配置文件,配置文件分为属性配置文件、Bean配置文件两种。Struts2的配置文件包括系统默认的配置文件: default.properties、struts-default.xml,以及插件配置文件、应用配置文件:struts-plugin.xml、struts.xml、struts.properties、web.xml。那么这六种配置文件的加载顺序,以下:

1. default.properties

2. struts-default.xml

3. struts-plugin.xml

4. struts.xml

5. struts.properties

6. web.xml

加载顺序以下图所示:

clip_image006

c) 加载静态资源配置参数: packages,该参数用来配置自动搜寻目录;

小提示:

FilterDispatcher 实现的StrutsStatics接口,没有定义业务方法,只定义了若干个常量。Struts2对经常使用的接口进行了从新封装,好比HttpServletRequest、HttpServletResponse、HttpServletContext等。以下图所示:

clip_image008

1.2 Struts2初始化源码分析

1. Struts2 Web应用启动时,根据web.xml配置的核心过滤器FilterDispatcher,会初始化FilterDispatcher:

clip_image010

2. 正如咱们知道的,过滤器初始化时,会自动调用init()方法进行初始化工做,因此在FilterDispatcher启动时,会自动调用init(FilterConfig filterConfig)方法,进行Struts2的初始化,首先在该方法中会建立org.apache.struts2.Dispatcher对象,将FilterDispatcher配置的初始化参数传到该对象中,而后调用dispatcher.init()方法加载并解析配置文件,最后加载静态资源配置参数packages。org.apache.struts2.dispatcher.FilterDispatcher.java源码以下图所示:

clip_image011

3. 在FilterDispatcher.init()方法中,首先建立Dispatcher类对象,并将FilterDispatcher配置的初始化参数传到对象中;相关代码,以下图所示:

clip_image013

4. 而后经过dispatcher.init()方法,加载并解析Struts2配置文件,配置文件的加载与解析是由Provider类来实现完成的,因此可分为两步:加载配置Provider、解析配置Provider,具体处理步骤以下:

a) 建立com.opensymphony.xwork2.config.ConfigurationManager,其中属性List<ContainerProvider> containerProviders存放全部配置Provider。

b) init_DefaultProperties():初始化一个用来加载default.properties的DefaultPropertiesProvider,并存入至containerProviders。

c) init_TraditionalXmlConfigurations():默认根据struts-default.xml,struts-plugin.xml,struts.xml (可根据init-param:config 修改加载路径) 分别建立三个 org.apache.struts2.config. StrutsXmlConfigurationProvider,并存入至containerProviders。

d) init_LegacyStrutsProperties():初始化初始化一个用来加载struts.properties的LegacyPropertiesConfigurationProvider,并存入至containerProviders。

e) init_CustomConfigurationProviders():根据init-param:configProviders初始化一个用户自定义实现的ConfigurationProvider接口的Provider,并存入至containerProviders。

f) init_FilterInitParameters():初始化一个用来加载web.xml中initParams配置的ConfigurationProvider, 并存入至containerProviders。

g) init_AliasStandardObjects() :初始化一个用来为所配置的Bean与具体类映射的BeanSelectionProvider,并存入至containerProviders。

h) init_PreloadConfiguration():以上几步存入ConfigurationProvider对象完毕后,按顺序循环调用上面几步存入的ConfigurationProvider的register、loadPackages、addPackage方法(先加载先解析),进行解析配置Provider。

小提示:

1. 加载配置Provider,其实就是加载配置文件;

2. 解析配置Provider,其实就是解析配置文件;

下面列出以上a-h步的相关代码,以下图所示:

1. Struts2中dispatcher.init()代码:

clip_image015

2. Struts2中init_PreloadConfiguration()方法代码:

clip_image017

3. XWork中configurationManager.getConfiguration()方法代码:

clip_image019

4. XWork中configuration.reloadContainer()方法代码:

clip_image021

5. Xwork中XmlConfigurationProvider.loadPackages()方法代码:

clip_image023

6. Xwork中XmlConfigurationProvider.addPackage ()方法代码:

clip_image025

4. 最后经过staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig))加载静态资源配置参数:packages,值得注意的是,还有另外三个固定的包和该参数进行拼接,分别是org.apache.struts2.static、template、和org.apache.struts2.interceptor.debugging,中间用空格隔开,通过解析将包名变成路径后存储到一个名叫pathPrefixes的数组中,这些目录中的文件会被自动搜寻;相关代码,以下图所示:

clip_image027

注:

关于源码分析,大概分为两种:流程源码分析、过程源码分析,因本人的初衷是流程源码分析,因此以上的分析是根据初始化处理流程顺序来进行分析的,并未对各个方法的过程细节作深刻的讲解,望见谅。