读者可能会关注,我们分析源码从哪个如下开始下手了,其实这个我以前也不知道,但是通过struts分析后,我也很快学会了怎么去分析Spring,Spring MVC, Mybatis等等这些主流的框架,所以现在让我们一步一步积累,学会了这种分析源码的方法,对以后自己研究开源框架很有益处。
首先我们能够看到Web.xml中有如下配置:
<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>
这里,就是struts2启动服务器加载所有配置的入口点,所有我们现在从StrutsPrepareAndExecuteFilter类开始分析
public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter
StrutsPrepareAndExecuteFilter类实现了Filter接口,现在很多人就会想到Servlet中的Filter,对!读者很聪明,就是Servlet的过滤器,那么他必然会实现如下三个方法:
public void init(FilterConfig filterConfig) throws ServletException
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
public void destroy()
下面我们就来分析init方法:
先让读者有一个总揽:
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();//这个创建对象啥也没做,很单纯哦
Dispatcher dispatcher = null;
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
init.cleanup();
}
}
现在我们把目标转移到InitOperations 类上面,
来瞧瞧这句话到底做了写什么???
init.initLogging(config);
跟踪代码改到方法,我们看到如下代码:
/**
* Initializes the internal Struts logging
*/
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();
}
}
}
很明显,这个就是加载日志文件的方法嘛,从我们配置的web.xml文件中读取该配置并加载该类。这里我们一般很少配置自己的日志处理类,所有该处几乎什么不执行!
然后我们返回StrutsPrepareAndExecuteFilter类中继续分析
dispatcher = init.initDispatcher(config);
进入该方法,看到代码如下:
/**
* Creates and initializes the dispatcher
*/
public Dispatcher initDispatcher( HostConfig filterConfig ) {
Dispatcher dispatcher = createDispatcher(filterConfig);
dispatcher.init();
return dispatcher;
}
这里,这个Dispatcher 类特别重要,在此我们来进行分析分析这个类
/**
* A utility class the actual dispatcher delegates most of its tasks to. Each instance
* of the primary dispatcher holds an instance of this dispatcher to be shared for
* all requests.
*
* @see org.apache.struts2.dispatcher.FilterDispatcher
*/
这是这个类的描述,一个实际中代理大多数任务的一个辅助类,
后面我们将要深度剖析服务器启动到底是怎么初始化Dispatcher 类的,该类特别重要,我将在下一篇博客中呈述。