天天看点

Tomcat8.x 路由表的建立->路由的匹配->Servlet的执行->数据的输出

路由表的建立->路由的匹配->Servlet的执行

//路由表的建立---------------1
		class org.apache.catalina.core.StandardService{
			protected void startInternal() throws LifecycleException {
//				org.apache.catalina.core.StandardEngine
//				org.apache.catalina.core.StandardHost
//					org.apache.catalina.core.StandardContext --- context
//						org.apache.catalina.core.StandardWrapper --- context.addChild(wrapper);
//						org.apache.tomcat.util.descriptor.web.SessionConfig --- context.getServletContext().getSessionCookieConfig().setXXX(...);
//						org.apache.tomcat.util.descriptor.web.FilterDef --- context.addFilterDef(filter);
//						org.apache.tomcat.util.descriptor.web.FilterMap --- context.addFilterMap(filterMap);
//						<listener-class>cn.java.listener.HelloListener</listener-class> --- context.addApplicationListener(listener);
				engine.start(); // 查找主机、上下文,构造对象树
				
				// 路由表的建立
				//!!! 查找默认虚拟主机/让 mapperListener 成为StandardEngine、StandardHost、StandardContext的监听器/注册路径信息到mapper中
		        mapperListener.start(); 
			}
		}
		
		// StandardContext的事件监听器,用来解析上下文
		class org.apache.catalina.startup.ContextConfig{
			private void configureContext(WebXml webxml) {
				// context === org.apache.catalina.core.StandardContext
		        for (FilterDef filter : webxml.getFilters().values()) { // 过滤器
		            if (filter.getAsyncSupported() == null) {
		                filter.setAsyncSupported("false");
		            }
		            context.addFilterDef(filter);
		        }
		        for (FilterMap filterMap : webxml.getFilterMappings()) { // 过滤器映射
		            context.addFilterMap(filterMap);
		        }
		        for (String listener : webxml.getListeners()) { // 应用监听器
		            context.addApplicationListener(listener);
		        }
		        for (ServletDef servlet : webxml.getServlets().values()) { // 添加Servlet对象
		        	// org.apache.catalina.core.StandardContext.createWrapper();
		        	// 创建org.apache.catalina.core.StandardWrapper对象
		        	// 给wrapper添加生命周期监听器
		        	// 给wrapper添加容器监听器
		            Wrapper wrapper = context.createWrapper();
		            // Description is ignored
		            // Display name is ignored
		            // Icons are ignored

		            // jsp-file gets passed to the JSP Servlet as an init-param

		            if (servlet.getLoadOnStartup() != null) {
		                wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
		            }
		            if (servlet.getEnabled() != null) {
		                wrapper.setEnabled(servlet.getEnabled().booleanValue());
		            }
		            wrapper.setName(servlet.getServletName()); // servlet的名称
		            Map<String,String> params = servlet.getParameterMap(); // Servlet的属性
		            for (Entry<String, String> entry : params.entrySet()) {
		                wrapper.addInitParameter(entry.getKey(), entry.getValue());
		            }
		            wrapper.setRunAs(servlet.getRunAs());
		            Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
		            for (SecurityRoleRef roleRef : roleRefs) {
		                wrapper.addSecurityReference(
		                        roleRef.getName(), roleRef.getLink());
		            }
		            wrapper.setServletClass(servlet.getServletClass()); // Servlet的类名
		            MultipartDef multipartdef = servlet.getMultipartDef();
		            if (multipartdef != null) {
		                if (multipartdef.getMaxFileSize() != null &&
		                        multipartdef.getMaxRequestSize()!= null &&
		                        multipartdef.getFileSizeThreshold() != null) {
		                    wrapper.setMultipartConfigElement(new MultipartConfigElement(
		                            multipartdef.getLocation(),
		                            Long.parseLong(multipartdef.getMaxFileSize()),
		                            Long.parseLong(multipartdef.getMaxRequestSize()),
		                            Integer.parseInt(
		                                    multipartdef.getFileSizeThreshold())));
		                } else {
		                    wrapper.setMultipartConfigElement(new MultipartConfigElement(
		                            multipartdef.getLocation()));
		                }
		            }
		            if (servlet.getAsyncSupported() != null) {
		                wrapper.setAsyncSupported(
		                        servlet.getAsyncSupported().booleanValue());
		            }
		            wrapper.setOverridable(servlet.isOverridable());
		            // wrapper ===  org.apache.catalina.core.StandardWrapper
		            context.addChild(wrapper);
		        }
		        for (Entry<String, String> entry :
		                webxml.getServletMappings().entrySet()) { // 添加Servlet映射
		            context.addServletMapping(entry.getKey(), entry.getValue());
		        }
		        SessionConfig sessionConfig = webxml.getSessionConfig();
		        if (sessionConfig != null) { // session配置
		            if (sessionConfig.getSessionTimeout() != null) {
		                context.setSessionTimeout(
		                        sessionConfig.getSessionTimeout().intValue());
		            }
		            SessionCookieConfig scc =
		                context.getServletContext().getSessionCookieConfig();//!!!
		            scc.setName(sessionConfig.getCookieName());
		            scc.setDomain(sessionConfig.getCookieDomain());
		            scc.setPath(sessionConfig.getCookiePath());
		            scc.setComment(sessionConfig.getCookieComment());
		            if (sessionConfig.getCookieHttpOnly() != null) {
		                scc.setHttpOnly(sessionConfig.getCookieHttpOnly().booleanValue());
		            }
		            if (sessionConfig.getCookieSecure() != null) {
		                scc.setSecure(sessionConfig.getCookieSecure().booleanValue());
		            }
		            if (sessionConfig.getCookieMaxAge() != null) {
		                scc.setMaxAge(sessionConfig.getCookieMaxAge().intValue());
		            }
		            if (sessionConfig.getSessionTrackingModes().size() > 0) {
		                context.getServletContext().setSessionTrackingModes(
		                        sessionConfig.getSessionTrackingModes());
		            }
		        }
			}
		}
		
		class org.apache.catalina.mapper.MapperListener{
			
			// 路由表的建立
			public void startInternal() throws LifecycleException {
				setState(LifecycleState.STARTING);

		        Engine engine = service.getContainer(); // org.apache.catalina.core.StandardEngine
		        if (engine == null) {
		            return;
		        }

		        findDefaultHost(); // 查找默认虚拟主机

		        addListeners(engine);// 让自己成为StandardEngine、StandardHost、StandardContext的监听器

		        Container[] conHosts = engine.findChildren();  // 注册路径信息到mapper中
		        for (Container conHost : conHosts) { // 
		            Host host = (Host) conHost; // org.apache.catalina.core.StandardHost
		            if (!LifecycleState.NEW.equals(host.getState())) {
		                // Registering the host will register the context and wrappers
		                registerHost(host);
		            }
		        }
			}
			
			// 添加虚拟主机
			private void registerHost(Host host) {
				String[] aliases = host.findAliases(); // org.apache.catalina.core.StandardHost
		        mapper.addHost(host.getName(), aliases, host); // mapper.hosts

		        for (Container container : host.findChildren()) {
		            if (container.getState().isAvailable()) { // org.apache.catalina.core.StandardContext
		                registerContext((Context) container);
		            }
		        }
			}
			
			// 添加上下文
			private void registerContext(Context context) {
				String contextPath = context.getPath();
		        if ("/".equals(contextPath)) {
		            contextPath = "";
		        }
		        Host host = (Host)context.getParent(); // org.apache.catalina.core.StandardHost

		        WebResourceRoot resources = context.getResources();
		        String[] welcomeFiles = context.findWelcomeFiles();
		        List<WrapperMappingInfo> wrappers = new ArrayList<>();

		        for (Container container : context.findChildren()) { // org.apache.catalina.core.StandardWrapper列表
		            prepareWrapperMappingInfo(context, (Wrapper) container, wrappers);
		        }

		        // 添加到map
		        mapper.addContextVersion(host.getName(), host, contextPath,
		                context.getWebappVersion(), context, welcomeFiles, resources,
		                wrappers);
			}
			
			private void prepareWrapperMappingInfo(Context context, Wrapper wrapper,
		            List<WrapperMappingInfo> wrappers) {
		        String wrapperName = wrapper.getName();// Servlet名称<servlet-name></servlet-name>
		        boolean resourceOnly = context.isResourceOnlyServlet(wrapperName);
		        String[] mappings = wrapper.findMappings();
		        for (String mapping : mappings) {
		            boolean jspWildCard = (wrapperName.equals("jsp")
		                                   && mapping.endsWith("/*"));
		            wrappers.add(new WrapperMappingInfo(mapping, wrapper, jspWildCard,
		                    resourceOnly));
		        }
		    }
		}
		
		// 路由表的映射---------------2
		class org.apache.catalina.connector.CoyoteAdapter{
			public void service(org.apache.coyote.Request req,
			        org.apache.coyote.Response res)
			       		 throws Exception {
				postParseSuccess = postParseRequest(req, request, res, response);//!!!!   解析scheme、查找路由、sessionID
				// request.getMappingData() 内部存储路由映射对象和StandardWrapper对象(StandardWrapper是Servlet的包装器)
			}
			
			// 解析请求
			protected boolean postParseRequest(org.apache.coyote.Request req, Request request,
			            org.apache.coyote.Response res, Response response) throws IOException, ServletException {
			    connector.getService().getMapper().map(serverName, decodedURI,
			            version, request.getMappingData()); // 映射出路由 -------------------并创建出相应对象!!!!
			}
		}
		
		// 路由映射
		class  org.apache.catalina.mapper.Mapper{
			
			public void map(MessageBytes host, MessageBytes uri, String version,
                 MappingData mappingData) throws IOException {
		        internalMap(host.getCharChunk(), uri.getCharChunk(), version,
		                mappingData);
		    }
			
			// 查找虚拟主机的映射,设置到mappingData.host
			// 查找上下文路径的映射,设置到mappingData.contextPath
			// 查找上下文的映射,设置到mappingData.context
			// 查找Servlet的映射,设置到mappingData.wrapper
			private final void internalMap(CharChunk host, CharChunk uri,
		            String version, MappingData mappingData) throws IOException {
				// Virtual host mapping 查找主机映射
		        MappedHost[] hosts = this.hosts;
		        MappedHost mappedHost = exactFindIgnoreCase(hosts, host);
		        mappingData.host = mappedHost.object;
		        
		        // Context mapping 上下文映射
		        ContextList contextList = mappedHost.contextList; // 虚拟主机的目录列表
		        MappedContext[] contexts = contextList.contexts;
		        // ...
		        mappingData.contextPath.setString(context.name); // 上下文地址
		        
		        ContextVersion contextVersion = null;
		        ContextVersion[] contextVersions = context.versions; // 上下文版本列表
		        mappingData.context = contextVersion.object;
		        mappingData.contextSlashCount = contextVersion.slashCount;
		        
		        // Wrapper mapping  Servlet的映射
		        if (!contextVersion.isPaused()) {
		            internalMapWrapper(contextVersion, uri, mappingData);
		        }
			}
			
			// 查找Servlet的映射,设置到mappingData.wrapper
			private final void internalMapWrapper(ContextVersion contextVersion,
                 CharChunk path,
                 MappingData mappingData) throws IOException {
				// Rule 1 -- Exact Match  Servlet的匹配
		        MappedWrapper[] exactWrappers = contextVersion.exactWrappers;
		        internalMapExactWrapper(exactWrappers, path, mappingData);
		        if (mappingData.wrapper == null) {
		        	//....
		        }
		        // ....
			}
		}
		
		// Servlet的执行---------------3
		class org.apache.catalina.connector.CoyoteAdapter{
			public void service(org.apache.coyote.Request req,
			        org.apache.coyote.Response res)
			       		 throws Exception {
				// 执行管道链条
                // org.apache.catalina.core.StandardService --- getService()
                // org.apache.catalina.core.StandardEngine --- getContainer()
                // org.apache.catalina.core.StandardPipeline --- getPipeline()
                // org.apache.catalina.core.StandardEngineValve --- getFirst()
                connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
                request.finishRequest();
                response.finishResponse(); // 输出数据,并关闭输出流
			}
		}
		
		class org.apache.catalina.core.StandardEngineValve{
			public final void invoke(Request request, Response response)
			        throws IOException, ServletException {
				// org.apache.catalina.core.StandardHostValve
		        host.getPipeline().getFirst().invoke(request, response);
			}
		}
		
		class org.apache.catalina.core.StandardHostValve{
			public final void invoke(Request request, Response response)
					throws IOException, ServletException {
				// org.apache.catalina.core.StandardContextValve
                context.getPipeline().getFirst().invoke(request, response); //!!!!
                
                response.setSuspended(false); 
			}
		}
		
		class org.apache.catalina.core.StandardContextValve{
			// request === org.apache.catalina.connector.Request
			Wrapper wrapper = request.getWrapper(); // Servlet对象
			// 执行Servlet请求 !!!! wrapper === org.apache.catalina.core.StandardWrapper
	        // org.apache.catalina.core.StandardWrapperValve.invoke(request, response);
	        wrapper.getPipeline().getFirst().invoke(request, response);
		}
		
		// 
		class org.apache.catalina.connector.Request{
	    	public Wrapper getWrapper() {
	            return mappingData.wrapper;
	        }
	    	public MappingData getMappingData() {
	            return mappingData;
	        }
	    }