Tomcat 8.x 从WebDotXml中的Servlet标签 -> Servlet的包装器StandardWrapper ->管道链末尾实例化Servlet对象


1、使用Digester解析Web.xml文件

2、把解析出来的<Servlet>节点对象,转成Servlet的包装器StandardWrapper

3、把StandardWrapper添加到父节点StandardContext

4、管道链末尾实例化Servlet对象、并执行init方法和service方法


class org.apache.catalina.startup.ContextConfig{
		
		protected void webConfig() {
			// -----------------------------------------
			// 1、使用Digester解析Web.xml文件
			// -----------------------------------------
			
			WebXml webXml = createWebXml();
			
			// 取得输入流 "d:/a/b/c/tomcat/webapps/dir1/WEB-INF/web.xml"
	        InputSource contextWebXml = getContextWebXmlSource();
	        if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) { // 解析文件 ,数据存入webXml
	            ok = false;
	        }
	        
	        // 使用 org.apache.jasper.servlet.JspServlet 包装  <jsp-file>/a/b/c/file.jsp</jsp-file>的文件
            convertJsps(webXml);
            // context === org.apache.catalina.core.StandardContext
            // 把解析处理的内容设置到 context 中 ,如:context.addFilterMap(filterMap);
            configureContext(webXml); //!!!!!
		}
	
		private void configureContext(WebXml webxml) {
			// -----------------------------------------
			// 2、把解析出来的<Servlet>节点对象,转成Servlet的包装器StandardWrapper
			// -----------------------------------------
			// servlet === org.apache.tomcat.util.descriptor.web.ServletDef
	        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的类名
	            
	            //servlet ===  org.apache.tomcat.util.descriptor.web.ServletDef
	            // 设置文件上传的配置
	//            <web-app>
	//	        	<servlet>
	//	        		<multipart-config>
	//		            <!-- 50MB max -->
	//		            <max-file-size>52428800</max-file-size>
	//		            <max-request-size>52428800</max-request-size>
	//		            <file-size-threshold>0</file-size-threshold>
	//		          </multipart-config>
	//	        	</servlet>
	//	        </web-app>
	            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 {
	                	// org.apache.catalina.core.StandardWrapper
	                    wrapper.setMultipartConfigElement(new MultipartConfigElement(
	                            multipartdef.getLocation()));
	                }
	            }
	            if (servlet.getAsyncSupported() != null) {
	                wrapper.setAsyncSupported(
	                        servlet.getAsyncSupported().booleanValue());
	            }
	            wrapper.setOverridable(servlet.isOverridable());
	            // -----------------------------------------
	    		// 3、把StandardWrapper添加到父节点StandardContext
	            // -----------------------------------------
	//          context === org.apache.catalina.core.StandardContext
	//          wrapper ===  org.apache.catalina.core.StandardWrapper
	            context.addChild(wrapper);
	        }
	        
	        for (Entry<String, String> entry :
	                webxml.getServletMappings().entrySet()) { // 添加Servlet映射
	            context.addServletMapping(entry.getKey(), entry.getValue());
	        }
		}
	}
	
	// -----------------------------------------
	// 4、管道链末尾实例化Servlet对象、并执行相应方法 
	// -----------------------------------------
	class org.apache.catalina.core.StandardContextValve{
		public final void invoke(Request request, Response response)
		        throws IOException, ServletException {
			 Wrapper wrapper = request.getWrapper(); // Servlet包装器对象org.apache.catalina.core.StandardWrapper
			// 执行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.core.StandardWrapperValve{
		public final void invoke(Request request, Response response)
		        throws IOException, ServletException {
			StandardWrapper wrapper = (StandardWrapper) getContainer();
	        Servlet servlet = null;
	        // org.apache.catalina.core.StandardContext
	        Context context = (Context) wrapper.getParent();
	        
	        // org.apache.catalina.core.StandardWrapper
        	//!!!!!!!!!
        	// !!!!! 加载Servlet类,创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
            // !!!!! 调用Servlet对象的init方法
            servlet = wrapper.allocate();
            
            // !!! 创建过滤器链条
            // Create the filter chain for this request
            ApplicationFilterChain filterChain =
                    ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
            
            // -----------------------------------------
    		// 4.3、调用Servlet对象的service方法
    		// -----------------------------------------
            // 执行过滤器链!!!! ,Servlet在过滤器链条的末端,过滤器执行后,就调用servlet.service(....)
        	// org.apache.catalina.connector.RequestFacade
        	// org.apache.catalina.connector.ResponseFacade
            filterChain.doFilter(request.getRequest(), response.getResponse());
            
            filterChain.release(); // 释放过滤器链资源
            wrapper.deallocate(servlet); // 释放Servlet资源
            
            if ((servlet != null) &&
                (wrapper.getAvailable() == Long.MAX_VALUE)) { // 释放StandardWrapper对象
                wrapper.unload();
            }
		}
	}
	
	class org.apache.catalina.core.StandardWrapper{
		
		protected final StandardWrapperFacade facade = new StandardWrapperFacade(this);
		
		public Servlet allocate() throws ServletException {
			// !!!!! 加载Servlet类,创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
            // !!!!! 调用Servlet对象的init方法
            instance = loadServlet();
		}
		
		public synchronized Servlet loadServlet() throws ServletException {
			//!!!实例管理器 org.apache.catalina.core.StandardContext
            // instanceManager === org.apache.catalina.core.DefaultInstanceManager
            InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
            
            // -----------------------------------------
    		// 4.1、实例化Servlet对象
    		// -----------------------------------------
            // 创建Servlet对象,反射Servlet对象内部的注解,如:@Resource声明的资源,并进行依赖注入到Servlet对象中!!!
        	// 如:servletClass === org.apache.jasper.servlet.JspServlet
        	// 如:servletClass === org.apache.catalina.servlets.DefaultServlet
        	// 如: servletClass === cn.java.note.HelloServlet
            // 如:servlet === new org.apache.jasper.servlet.JspServlet()
        	// 如:servlet === new org.apache.catalina.servlets.DefaultServlet()
        	// 如: servlet === new cn.java.note.HelloServlet()
            servlet = (Servlet) instanceManager.newInstance(servletClass);
            
            // 处理Servlet的安全注解
            processServletSecurityAnnotation(servlet.getClass());

            // Special handling for ContainerServlet instances
            if ((servlet instanceof ContainerServlet) &&
                    (isContainerProvidedServlet(servletClass) ||
                            ((Context) getParent()).getPrivileged() )) {
                ((ContainerServlet) servlet).setWrapper(this); // 容器Servlet实例,设置对父节点的依赖
            }
            
            // 调用Servlet的初始化方法init
            initServlet(servlet);

            fireContainerEvent("load", this); // 触发容器事件 ContainerListener
		}
		
		
		private synchronized void initServlet(Servlet servlet)
	            throws ServletException {
			// -----------------------------------------
    		// 4.2、调用Servlet对象的init方法
    		// -----------------------------------------
			// 如:servlet === new org.apache.jasper.servlet.JspServlet()
        	// 如:servlet === new org.apache.catalina.servlets.DefaultServlet()
        	// 如: servlet === new cn.java.note.HelloServlet()
			// 调用Servlet的初始化方法init
        	// facade = new StandardWrapperFacade(this);
            servlet.init(facade);
		}
		
		@Override
	    public ServletContext getServletContext() {
	        if (parent == null)
	            return (null);
	        else if (!(parent instanceof Context))
	            return (null);
	        else
	        	// parent = org.apache.catalina.core.StandardContext
	        	// return org.apache.catalina.core.StandardContext.getServletContext()
	        	// return org.apache.catalina.core.ApplicationContextFacade
	            return (((Context) parent).getServletContext()); // !!!

	    }
		
	}
	
	// StandardWrapper接口屏蔽类StandardWrapperFacade
	class org.apache.catalina.core.StandardWrapperFacade  implements ServletConfig {
			public StandardWrapperFacade(StandardWrapper config) {
		        super();
		        this.config = config;
		    }
			
		 	@Override
		    public ServletContext getServletContext() {
		        if (context == null) {
		        	// config == org.apache.catalina.core.StandardWrapper;
		        	// context == org.apache.catalina.core.StandardWrapper.getServletContext();
		        	// context == org.apache.catalina.core.StandardContext.getServletContext()
		        	// context == org.apache.catalina.core.ApplicationContextFacade
		            context = config.getServletContext();
		            if (context instanceof ApplicationContext) {
		                context = ((ApplicationContext) context).getFacade();
		            }
		        }
		        return (context);
		    }
		 	
		 	 @Override
		     public String getInitParameter(String name) {
		         return config.getInitParameter(name);
		     }


		     @Override
		     public Enumeration<String> getInitParameterNames() {
		         return config.getInitParameterNames();
		     }
	}
	
	// 上下文对象StandardContext
	class org.apache.catalina.core.StandardContext{
		
		@Override
	    public ServletContext getServletContext() {

	        if (context == null) {
	            context = new ApplicationContext(this);//!!!!
	            if (altDDName != null)
	                context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
	        }
	        return (context.getFacade());

	    }
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
31-May-2023 21:55:15.359 信息 [http-nio-8080-exec-6] org.apache.catalina.core.ApplicationContext.log 将servlet[com.LdfandWh.servlet.CheckCodeServlet]标记为不可用 31-May-2023 21:55:15.359 严重 [http-nio-8080-exec-6] org.apache.catalina.core.StandardWrapperValve.invoke 分配异常的servlet [com.LdfandWh.servlet.CheckCodeServlet] java.lang.ClassNotFoundException: com.LdfandWh.servlet.CheckCodeServlet at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1365) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188) at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:539) at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:520) at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:150) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1042) at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:761) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)
最新发布
06-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值