几个重要的事件监听器
org.apache.catalina.startup.HostConfig 主要识别上下文
org.apache.catalina.startup.ContextConfig 主要解析上下文中的web.xml文件
class org.apache.catalina.core.StandardServer{
protected void startInternal() throws LifecycleException {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
class org.apache.catalina.core.StandardService{
protected void startInternal() throws LifecycleException {
engine.start(); // 启动子节点 !!! org.apache.catalina.core.StandardEngine
for (Executor executor: executors) {
executor.start();
}
//!!! 查找默认虚拟主机/让 mapperListener 成为StandardEngine、StandardHost、StandardContext的监听器/注册路径信息到mapper中
mapperListener.start();
for (Connector connector: connectors) {
connector.start(); //!!!
}
}
}
class org.apache.catalina.core.StandardEngine{
protected synchronized void startInternal() throws LifecycleException {
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (int i = 0; i < children.length; i++) { // children[i] = org.apache.catalina.core.StandardHost
results.add(startStopExecutor.submit(new StartChild(children[i]))); // 提交执行子节点
}
boolean fail = false;
for (Future<Void> result : results) {
try {
result.get();
} catch (Exception e) {
fail = true;
}
}
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start(); // 启动管道
// org.apache.catalina.startup.EngineConfig
setState(LifecycleState.STARTING); // 触发事件
}
}
class org.apache.catalina.core.StandardHost{ // 可以走到这一层
protected synchronized void startInternal() throws LifecycleException {
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (int i = 0; i < children.length; i++) { // children[i] = org.apache.catalina.core.StandardHost
results.add(startStopExecutor.submit(new StartChild(children[i]))); // 提交执行子节点
}
boolean fail = false;
for (Future<Void> result : results) {
try {
result.get();
} catch (Exception e) {
fail = true;
}
}
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start(); // 启动管道
// org.apache.catalina.startup.HostConfig 部署应用
setState(LifecycleState.STARTING); // 触发事件
}
public void addChild(Container child) {
child.setParent(this); // May throw IAE 保存对父节点的依赖
children.put(child.getName(), child); // 添加到父节点中
if ((getState().isAvailable() ||
LifecycleState.STARTING_PREP.equals(getState())) &&
startChildren) {
// org.apache.catalina.core.StandardContext
child.start(); // 启动子节点 ,触发事件子节点的事件
}
}
}
org.apache.catalina.startup.HostConfig{
public void lifecycleEvent(LifecycleEvent event) {
start();
}
public void start() {
if (host.getDeployOnStartup()) // true 启动的时候部署
deployApps();// 部署应用
}
protected void deployApps() {
File appBase = host.getAppBaseFile(); // 绝对路径 d:/a/b/c/tomcat/webapps
File configBase = host.getConfigBaseFile(); // 绝对路径 d:/a/b/c/tomcat/conf/Catalina/localhost
String[] filteredAppPaths = filterAppPaths(appBase.list()); // 去除要忽略的目录
// Deploy XML descriptors from configBase 根据 d:/a/b/c/tomcat/conf/Catalina/localhost/context1.xml xml文件部署
deployDescriptors(configBase, configBase.list());
// Deploy WARs 根据 d:/a/b/c/tomcat/webapps/dir1.war war文件部署
deployWARs(appBase, filteredAppPaths);
// Deploy expanded folders 根据 d:/a/b/c/tomcat/webapps/dir1 目录文件部署
deployDirectories(appBase, filteredAppPaths);
}
protected void deployDirectories(File appBase, String[] files) {
// ....
for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase("META-INF"))
continue;
if (files[i].equalsIgnoreCase("WEB-INF"))
continue;
File dir = new File(appBase, files[i]);
if (dir.isDirectory()) {
ContextName cn = new ContextName(files[i], false);
if (isServiced(cn.getName()) || deploymentExists(cn.getName()))
continue;
// results.add(es.submit(new DeployDirectory(this, cn, dir)));
this.deployDirectory(...);
}
}
//...
}
protected void deployDirectory(ContextName cn, File dir) {
// org.apache.catalina.core.StandardContext
context = (Context) Class.forName(contextClass).newInstance();
Class<?> clazz = Class.forName(host.getConfigClass()); // org.apache.catalina.startup.ContextConfig
LifecycleListener listener =
(LifecycleListener) clazz.newInstance();
context.addLifecycleListener(listener);
context.setName(cn.getName());
context.setPath(cn.getPath());
context.setWebappVersion(cn.getVersion());
context.setDocBase(cn.getBaseName());
// org.apache.catalina.core.StandardHost
host.addChild(context);
}
}
class org.apache.catalina.core.StandardContext{
protected synchronized void startInternal() throws LifecycleException {
setConfigured(false); // 触发配置事件
setResources(new StandardRoot(this));//!!! 设置资源
// 创建org.apache.catalina.webresources.DirResourceSet
resourcesStart(); // !!! 启动资源
if (cookieProcessor == null) { // cookie处理器
cookieProcessor = new Rfc6265CookieProcessor();
}
// Initialize character set mapper
getCharsetMapper(); // 字符映射器
// Post work directory
// context.setAttribute(ServletContext.TEMPDIR, "d:/a/b/tomcat/work/Catalina/localhost/dir1"); // 临时目录
// context.setAttributeReadOnly(ServletContext.TEMPDIR); // 只读目录
postWorkDirectory(); // 部署工作目录
// 读取并解析“d:/a/c/d/tomcat/conf/web.xml”,读取并解析"d:/a/b/tomcat/conf/Catalina/localhost/web.xml.default"
// 取得输入流 "d:/a/b/c/tomcat/webapps/dir1/WEB-INF/web.xml"
// 合并配置文件内容
// 合并全局配置
// 使用 org.apache.jasper.servlet.JspServlet 包装 <jsp-file>/a/b/c/file.jsp</jsp-file>的文件
// 把解析处理的内容设置到 context 中 ,如:context.addFilterMap(filterMap);
// Notify our interested LifecycleListeners 触发事件监听器 org.apache.catalina.startup.ContextConfig
fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null); // 配置启动事件 "configure_start"----------------------
// 触发事件监听器 org.apache.catalina.startup.ContextConfig
setState(LifecycleState.STARTING);
}
}
class org.apache.catalina.startup.ContextConfig{
public void lifecycleEvent(LifecycleEvent event) {
try {
context = (Context) event.getLifecycle(); // 取得触发者 org.apache.catalina.core.StandardContext
} 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)) { // "configure_start"
configureStart();
} 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();
}
}
protected synchronized void configureStart() {
// 读取并解析“d:/a/c/d/tomcat/conf/web.xml”,读取并解析"d:/a/b/tomcat/conf/Catalina/localhost/web.xml.default"
// 取得输入流 "d:/a/b/c/tomcat/webapps/dir1/WEB-INF/web.xml"
// 合并配置文件内容
// 合并全局配置
// 使用 org.apache.jasper.servlet.JspServlet 包装 <jsp-file>/a/b/c/file.jsp</jsp-file>的文件
// 把解析处理的内容设置到 context 中 ,如:context.addFilterMap(filterMap);
webConfig();//!!!! 核心
}
protected void webConfig() {
// 读取并解析“d:/a/c/d/tomcat/conf/web.xml”,读取并解析"d:/a/b/tomcat/conf/Catalina/localhost/web.xml.default"
defaults.add(getDefaultWebXmlFragment(webXmlParser));
WebXml webXml = createWebXml();
// Parse context level web.xml
// 取得输入流 "d:/a/b/c/tomcat/webapps/dir1/WEB-INF/web.xml"
InputSource contextWebXml = getContextWebXmlSource();
if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) { // 解析文件 ,数据存入webXml
ok = false;
}
Map<String,WebXml> fragments = processJarsForWebFragments(webXml, webXmlParser); // 解析jar包的中的web-fragment.xml文件
if (ok) {
ok = webXml.merge(orderedFragments); // 合并配置文件内容
}
webXml.merge(defaults); // 合并全局配置
// Step 8. Convert explicitly mentioned jsps to servlets
if (ok) {
// 使用 org.apache.jasper.servlet.JspServlet 包装 <jsp-file>/a/b/c/file.jsp</jsp-file>的文件
convertJsps(webXml);
}
// Step 9. Apply merged web.xml to Context
if (ok) {
// context === org.apache.catalina.core.StandardContext
configureContext(webXml); // 把解析处理的内容设置到 context 中 ,如:context.addFilterMap(filterMap);
}
}
}