ContextConfig
还是先看看源码,看一下这个监听器做了什么。
public void lifecycleEvent(LifecycleEvent event) {
// Identify the context we are associated with
try {
context = (Context) event.getLifecycle();
} catch (ClassCastException e) {
log.error(sm.getString("contextConfig.cce", event.getLifecycle()),
e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
configureStart();// 里面调用了webConfig()
} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
beforeStart();
} else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
// Restore docBase for management tools
if (originalDocBase != null) {
context.setDocBase(originalDocBase);
}
} else if (event.getType().equals(Lifecycle.CONFIGURE_STOP_EVENT)) {
configureStop();
} else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) {
init();
} else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) {
destroy();
}
}
接着看configureStart():
protected synchronized void configureStart() {
// Called from StandardContext.start()
if (log.isDebugEnabled()) {
log.debug(sm.getString("contextConfig.start"));
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("contextConfig.xmlSettings",
context.getName(),
Boolean.valueOf(context.getXmlValidation()),
Boolean.valueOf(context.getXmlNamespaceAware())));
}
webConfig();/* 这个方法解析了web.xml文件 */
if (!context.getIgnoreAnnotations()) {
applicationAnnotationsConfig();
}
if (ok) {
validateSecurityRoles();
}
// Configure an authenticator if we need one
if (ok) {
authenticatorConfig();
}
// Dump the contents of this pipeline if requested
if (log.isDebugEnabled()) {
log.debug("Pipeline Configuration:");
Pipeline pipeline = context.getPipeline();
Valve valves[] = null;
if (pipeline != null) {
valves = pipeline.getValves();
}
if (valves != null) {
for (int i = 0; i < valves.length; i++) {
log.debug(" " + valves[i].getClass().getName());
}
}
log.debug("======================");
}
// Make our application available if no problems were encountered
if (ok) {
context.setConfigured(true);
} else {
log.error(sm.getString("contextConfig.unavailable"));
context.setConfigured(false);
}
}
接着看webConfig:
protected void webConfig() {
/*
* Anything and everything can override the global and host defaults.
* This is implemented in two parts - Handle as a web fragment that gets
* added after everything else so everything else takes priority - Mark
* Servlets as overridable so SCI configuration can replace
* configuration from the defaults
*/
/*
* The rules for annotation scanning are not as clear-cut as one might
* think. Tomcat implements the following process: - As per SRV.1.6.2,
* Tomcat will scan for annotations regardless of which Servlet spec
* version is declared in web.xml. The EG has confirmed this is the
* expected behaviour. - As per
* http://java.net/jira/browse/SERVLET_SPEC-36, if the main web.xml is
* marked as metadata-complete, JARs are still processed for SCIs. - If
* metadata-complete=true and an absolute ordering is specified, JARs
* excluded from the ordering are also excluded from the SCI processing.
* - If an SCI has a @HandlesType annotation then all classes (except
* those in JARs excluded from an absolute ordering) need to be scanned
* to check if they match.
*/
WebXmlParser webXmlParser = new WebXmlParser(
context.getXmlNamespaceAware(), context.getXmlValidation(),
context.getXmlBlockExternal());
Set<WebXml> defaults = new HashSet<>();
defaults.add(getDefaultWebXmlFragment(webXmlParser));
WebXml webXml = createWebXml();
// Parse context level web.xml
// 解析context级的web.xml
InputSource contextWebXml = getContextWebXmlSource();
if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {// 解析web.xml并创建对象
ok = false;
}
ServletContext sContext = context.getServletContext();
// Ordering is important here
// 顺序在这里很重要
// Step 1. Identify all the JARs packaged with the application and those
// provided by the container. If any of the application JARs have a
// web-fragment.xml it will be parsed at this point. web-fragment.xml
// files are ignored for container provided JARs.
// 第一步 .识别所有的JARs 包用那些container提供的应用。如果有任何应用JARs有web-fragment.xml将在此刻解析
// 对于那些提供了JARs的container,web-fragment.xml被忽略。
Map<String, WebXml> fragments = processJarsForWebFragments(webXml,
webXmlParser);
// Step 2. Order the fragments.
// 第二步,给碎片进行排序
Set<WebXml> orderedFragments = null;
orderedFragments = WebXml
.orderWebFragments(webXml, fragments, sContext);
// Step 3. Look for ServletContainerInitializer implementations
// 查找ServletContainerInitializer的实现
if (ok) {
processServletContainerInitializers();
}
if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
// Step 4. Process /WEB-INF/classes for annotations and
// @HandlesTypes matches
// 第四步.为注释传递 /WEB-INF.classes ,处理类型匹配
Map<String, JavaClassCacheEntry> javaClassCache = new HashMap<>();
if (ok) {
WebResource[] webResources = context.getResources()
.listResources("/WEB-INF/classes");
for (WebResource webResource : webResources) {
// Skip the META-INF directory from any JARs that have been
// expanded in to WEB-INF/classes (sometimes IDEs do this).
if ("META-INF".equals(webResource.getName())) {
continue;
}
processAnnotationsWebResource(webResource, webXml,
webXml.isMetadataComplete(), javaClassCache);
}
}
// Step 5. Process JARs for annotations and
// @HandlesTypes matches - only need to process those fragments we
// are going to use (remember orderedFragments includes any
// container fragments)
// 第5步 为annotations 传递JARs
if (ok) {
processAnnotations(orderedFragments,
webXml.isMetadataComplete(), javaClassCache);
}
// Cache, if used, is no longer required so clear it
javaClassCache.clear();
}
if (!webXml.isMetadataComplete()) {
// Step 6. Merge web-fragment.xml files into the main web.xml
// file.
// 第六步.合并web-fragment.xml变成一个主要的web.xml
if (ok) {
ok = webXml.merge(orderedFragments);
}
// Step 7. Apply global defaults
// Have to merge defaults before JSP conversion since defaults
// provide JSP servlet definition.
// 第七步.应用全局的缺省设置
// 必须在JSP转换之前因为缺省的值提供了JSP servlet的定义
webXml.merge(defaults);
// Step 8. Convert explicitly mentioned jsps to servlets
// 第八步.转换明确提及的jsps到servlets
if (ok) {
convertJsps(webXml);
}
// Step 9. Apply merged web.xml to Context
// 第九步.应用碎片的web.xml到这个context
if (ok) {
configureContext(webXml);/* 创建了wrapper */
}
} else {
webXml.merge(defaults);
convertJsps(webXml);
configureContext(webXml);
}
if (context.getLogEffectiveWebXml()) {
log.info("web.xml:\n" + webXml.toXml());
}
// Always need to look for static resources
// Step 10. Look for static resources packaged in JARs
// 第十步 查找一些静态的资源包在JARs里面
if (ok) {
// Spec does not define an order.
// Use ordered JARs followed by remaining JARs
Set<WebXml> resourceJars = new LinkedHashSet<>();
for (WebXml fragment : orderedFragments) {
resourceJars.add(fragment);
}
for (WebXml fragment : fragments.values()) {
if (!resourceJars.contains(fragment)) {
resourceJars.add(fragment);
}
}
processResourceJARs(resourceJars);
// See also StandardContext.resourcesStart() for
// WEB-INF/classes/META-INF/resources configuration
}
// Step 11. Apply the ServletContainerInitializer config to the
// context
// 第十一步. 应用ServletContainerInitializer配置给这个context
if (ok) {
for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry : initializerClassMap
.entrySet()) {
if (entry.getValue().isEmpty()) {
context.addServletContainerInitializer(entry.getKey(), null);
} else {
context.addServletContainerInitializer(entry.getKey(),
entry.getValue());
}
}
}
}
1.解析xml文件
2.创建wrapper,并调用addchild方法作为Context的子容器,
这样就可以loadonstartup时调用load方法。加载standardWrapper。
Tomcat8.5源码-StandardWrapper