从点击服务器(这里说到的服务器为tomcat)的start来启动服务,到对服务器发出请求,中间经历了一个怎样的过程?
启动流程:
WEB服务器启动:
1- 加载解析 $CATALINA_HOME/conf/web.xml
2-加载每个WEB app 下的 web.xml
3-对于struts2框架,在web.xml中,会配置拦截器,如下。这时候会初始化 StrutsPrepareAndExecuteFilter类
<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>
4-在StrutsPrepareAndExecuteFilter类中的init方法中初始化struts2的配置文件:
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(dispatcher);
execute = new ExecuteOperations(dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
dispatcher.cleanUpAfterInit();
}
init.cleanup();
}
}
5:跟踪代码,在Dispatcher类中的init方式中,初始化具体的配置文件
public void init() {
if (configurationManager == null) {
configurationManager = createConfigurationManager(DefaultBeanSelectionProvider.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);
}
}
errorHandler.init(servletContext);
} catch (Exception ex) {
if (LOG.isErrorEnabled())
LOG.error("Dispatcher initialization failed", ex);
throw new StrutsException(ex);
}
}
[1] – init_DefaultProperties()
位置:struts-core-2.3.32.jar -> org/apache/struts2/default.properties
作用:用于配置Struts2常量的默认值
[2]–init_TraditionalXmlConfigurations()
这里会初始话三个配置文件:
private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";
即:struts-default.xml,struts-plugin.xml,struts.xml
struts-default.xml
位置: struts-core-2.3.32.jar 类路径的根路径下
作用:Struts2核心配置struts-plugin.xml
作用:strut2插件的配置文件struts.xml
位置:用户类路径的根路径 /src
作用:用户编写的业务处理映射(Action)
[3]–init_LegacyStrutsProperties()
位置:用户类路径的根路径 /src
作用:配置Struts2的常量(非必须)
[5]–init_CustomConfigurationProviders()
用于配置 struts.custom.properties
位置:用户类路径的根路径 /src
作用:配置用户自定义常量
启动流程小结:
- 加载解析 $CATALINA_HOME/conf/web.xml(tomcat)
- 初始化 StrutsPrepareAndExecuteFilter
- 然后按序加载下面配置文件
- default.properties,
- struts-default.xml, struts-plugin.xml,struts.xml,
- struts.properties,
- struts.custom.properties
请求流程
当求服务器发出请求的时候,首先会被StrutsPrepareAndExecuteFilter类的doFilter方法拦截:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response, true);//获取是否有相应的action
if (mapping == null) { //对于静态资源的处理
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
//有相应的action时
execute.executeAction(request, response, mapping);
}
}
} finally {
prepare.cleanupRequest(request);
}
}
然后调用响应的拦截器:
if (interceptors.hasNext()) { //这里会被反复的调用,直到所有的拦截器都被调用完,然后执行相应的action方法
final InterceptorMapping interceptor = interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
resultCode = invokeActionOnly();
}