Tomcat8.x 启动start()->上下文发布->上下文中web.xml文件解析


几个重要的事件监听器

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);
		            }
			 }
		}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值