对以上的StandardWrapperValve#invoke进行说解
- if (!unavailable) {
- //servlet行行在这一步
- servlet = wrapper.allocate();
- }
public Servlet allocate() throws ServletException { // If we are currently unloading this servlet, throw an exception if (unloading) throw new ServletException (sm.getString("standardWrapper.unloading", getName())); boolean newInstance = false; // If not SingleThreadedModel, return the same instance every time //在我们平时中没有设置,默认是单例模式,这一步实现每一次都返回相同的实例 if (!singleThreadModel) { // Load and initialize our instance if necessary if (instance == null) { synchronized (this) { //在实例为空时才创建 if (instance == null) { try { if (log.isDebugEnabled()) log.debug("Allocating non-STM instance"); //创建实例 instance = loadServlet(); // For non-STM, increment here to prevent a race // condition with unload. Bug 43683, test case #3 if (!singleThreadModel) { newInstance = true; // countAllocated.incrementAndGet(); } } catch (ServletException e) { throw e; } catch (Throwable e) { throw new ServletException (sm.getString("standardWrapper.allocate"), e); } } } } if (!singleThreadModel) { if (log.isTraceEnabled()) log.trace(" Returning non-STM instance"); // For new instances, count will have been incremented at the // time of creation if (!newInstance) { countAllocated.incrementAndGet(); } return (instance); } } //每一次都返回一个实例存放在instancePool中 synchronized (instancePool) { while (countAllocated.get() >= nInstances) { // Allocate a new instance if possible, or else wait if (nInstances < maxInstances) { try { instancePool.push(loadServlet()); nInstances++; } catch (ServletException e) { throw e; } catch (Throwable e) { throw new ServletException (sm.getString("standardWrapper.allocate"), e); } } else { try { instancePool.wait(); } catch (InterruptedException e) { ; } } } if (log.isTraceEnabled()) log.trace(" Returning allocated STM instance"); countAllocated.incrementAndGet(); return (Servlet) instancePool.pop(); } }
以上这一步在我们平时使用时会经常遇到,,servlet的创建是一个多线程单实例的,所以共享全局变量,所以在使用servlet
时应尽量避免定义全局变量
对#loadServlet进行详解
public synchronized Servlet loadServlet() throws ServletException { // Nothing to do if we already have an instance or an instance pool //如果有实例时直接返回 if (!singleThreadModel && (instance != null)) return instance; PrintStream out = System.out; if (swallowOutput) { SystemLogHandler.startCapture(); } Servlet servlet; try { long t1=System.currentTimeMillis(); // If this "servlet" is really a JSP file, get the right class. // HOLD YOUR NOSE - this is a kludge that avoids having to do special // case Catalina-specific code in Jasper - it also requires that the // servlet path be replaced by the <jsp-file> element content in // order to be completely effective //所访问的servlet的类路径名 String actualClass = servletClass; if ((actualClass == null) && (jspFile != null)) { Wrapper jspWrapper = (Wrapper) ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME); if (jspWrapper != null) { actualClass = jspWrapper.getServletClass(); // Merge init parameters String paramNames[] = jspWrapper.findInitParameters(); for (int i = 0; i < paramNames.length; i++) { if (parameters.get(paramNames[i]) == null) { parameters.put (paramNames[i], jspWrapper.findInitParameter(paramNames[i])); } } } } // Complain if no servlet class has been specified if (actualClass == null) { unavailable(null); throw new ServletException (sm.getString("standardWrapper.notClass", getName())); } // Acquire an instance of the class loader to be used Loader loader = getLoader(); if (loader == null) { unavailable(null); throw new ServletException (sm.getString("standardWrapper.missingLoader", getName())); } //获取werbappclassloader ClassLoader classLoader = loader.getClassLoader(); // Special case class loader for a container provided servlet // if (isContainerProvidedServlet(actualClass) && ! ((Context)getParent()).getPrivileged() ) { // If it is a priviledged context - using its own // class loader will work, since it's a child of the container // loader classLoader = this.getClass().getClassLoader(); } // Load the specified servlet class from the appropriate class loader Class classClass = null; try { if (SecurityUtil.isPackageProtectionEnabled()){ final ClassLoader fclassLoader = classLoader; final String factualClass = actualClass; try{ classClass = (Class)AccessController.doPrivileged( new PrivilegedExceptionAction(){ public Object run() throws Exception{ if (fclassLoader != null) { //进行类加载 return fclassLoader.loadClass(factualClass); } else { return Class.forName(factualClass); } } }); } catch(PrivilegedActionException pax){ Exception ex = pax.getException(); if (ex instanceof ClassNotFoundException){ throw (ClassNotFoundException)ex; } else { getServletContext().log( "Error loading " + fclassLoader + " " + factualClass, ex ); } } } else { if (classLoader != null) { classClass = classLoader.loadClass(actualClass); } else { classClass = Class.forName(actualClass); } } } catch (ClassNotFoundException e) { unavailable(null); getServletContext().log( "Error loading " + classLoader + " " + actualClass, e ); throw new ServletException (sm.getString("standardWrapper.missingClass", actualClass), e); } if (classClass == null) { unavailable(null); throw new ServletException (sm.getString("standardWrapper.missingClass", actualClass)); } // Instantiate and initialize an instance of the servlet class itself try { servlet = (Servlet) classClass.newInstance(); // Annotation processing if (!((Context) getParent()).getIgnoreAnnotations()) { if (getParent() instanceof StandardContext) { ((StandardContext)getParent()).getAnnotationProcessor().processAnnotations(servlet); ((StandardContext)getParent()).getAnnotationProcessor().postConstruct(servlet); } } } catch (ClassCastException e) { unavailable(null); // Restore the context ClassLoader throw new ServletException (sm.getString("standardWrapper.notServlet", actualClass), e); } catch (Throwable e) { unavailable(null); // Added extra log statement for Bugzilla 36630: // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630 if(log.isDebugEnabled()) { log.debug(sm.getString("standardWrapper.instantiate", actualClass), e); } // Restore the context ClassLoader throw new ServletException (sm.getString("standardWrapper.instantiate", actualClass), e); } // Check if loading the servlet in this web application should be // allowed if (!isServletAllowed(servlet)) { throw new SecurityException (sm.getString("standardWrapper.privilegedServlet", actualClass)); } // Special handling for ContainerServlet instances if ((servlet instanceof ContainerServlet) && (isContainerProvidedServlet(actualClass) || ((Context)getParent()).getPrivileged() )) { ((ContainerServlet) servlet).setWrapper(this); } classLoadTime=(int) (System.currentTimeMillis() -t1); // Call the initialization method of this servlet //该Servlet的初始化,只实现一次 try { instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, servlet); if( Globals.IS_SECURITY_ENABLED) { Object[] args = new Object[]{((ServletConfig)facade)}; SecurityUtil.doAsPrivilege("init", servlet, classType, args); args = null; } else { servlet.init(facade); } // Invoke jspInit on JSP pages //jsp转换成servlet的初始化 if ((loadOnStartup >= 0) && (jspFile != null)) { // Invoking jspInit DummyRequest req = new DummyRequest(); req.setServletPath(jspFile); req.setQueryString(Constants.PRECOMPILE + "=true"); DummyResponse res = new DummyResponse(); if( Globals.IS_SECURITY_ENABLED) { Object[] args = new Object[]{req, res}; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args); args = null; } else { servlet.service(req, res); } } instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet); } catch (UnavailableException f) { instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f); unavailable(f); throw f; } catch (ServletException f) { instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f); // If the servlet wanted to be unavailable it would have // said so, so do not call unavailable(null). throw f; } catch (Throwable f) { getServletContext().log("StandardWrapper.Throwable", f ); instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f); // If the servlet wanted to be unavailable it would have // said so, so do not call unavailable(null). throw new ServletException (sm.getString("standardWrapper.initException", getName()), f); } // Register our newly initialized instance singleThreadModel = servlet instanceof SingleThreadModel; if (singleThreadModel) { if (instancePool == null) instancePool = new Stack(); } fireContainerEvent("load", this); loadTime=System.currentTimeMillis() -t1; } finally { if (swallowOutput) { String log = SystemLogHandler.stopCapture(); if (log != null && log.length() > 0) { if (getServletContext() != null) { getServletContext().log(log); } else { out.println(log); } } } } return servlet; }
从以上步骤可得到该servlet的实例,并用已经初始化过
现在对StandardWrapperValve#invoke
- //这里面开始对过滤器进行处理
- filterChain.doFilter(request.getRequest(),
- response.getResponse());
这里面对过滤器进行了执行ApplicationFilterChain#doFilter
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; try { java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction() { public Object run() throws ServletException, IOException { internalDoFilter(req,res); return null; } } ); } catch( PrivilegedActionException pe) { Exception e = pe.getException(); if (e instanceof ServletException) throw (ServletException) e; else if (e instanceof IOException) throw (IOException) e; else if (e instanceof RuntimeException) throw (RuntimeException) e; else throw new ServletException(e.getMessage(), e); } } else { //这一步才是真正的执行 internalDoFilter(request,response); } }
#internalDoFilter(rquest,response)
private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = null; try { //获取过滤器 filter = filterConfig.getFilter(); support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response); if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res, this}; SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal); args = null; } else { //进行过滤 filter.doFilter(request, response, this); } support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response); } catch (IOException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (ServletException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (RuntimeException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (Throwable e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw new ServletException (sm.getString("filterChain.filter"), e); } return; } // We fell off the end of the chain -- call the servlet instance try { if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(request); lastServicedResponse.set(response); } support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response); if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) { if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res}; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal); args = null; } else { servlet.service((HttpServletRequest) request, (HttpServletResponse) response); } } else { //有过滤器,先过滤再执行servlet的service的方法 servlet.service(request, response); } support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response); } catch (IOException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (ServletException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (RuntimeException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (Throwable e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw new ServletException (sm.getString("filterChain.servlet"), e); } finally { if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(null); lastServicedResponse.set(null); } } }
这样的过滤器已经执行,servlet也已经执行....接下来做些释放工程
相关推荐
3-5Tomcat响应请求源码与nio处理请求源码实现.mp4
apache-tomcat-9.0.8 其中有完整的源码 bin目录下有你所想要的所有完整的
从零手写Tomcat【源码】【abl-tomcat-004】【基础完善-处理动态资源请求】 文章地址:https://blog.csdn.net/m0_37969197/article/details/124096403 目录地址:...
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台...
Tomcat启动流程分析 组件的生命周期管理 用Lifecycle管理启动、停止、关闭 Lifecycle接口预览 ...根据请求地址匹配正确的容器进行处理 将响应返回客户端 Container设计 Servlet容器的实现。
从零手写Tomcat【源码】【abl-tomcat-005】【添加多线程,处理请求】 文章地址:https://blog.csdn.net/m0_37969197/article/details/124098639 目录地址:...
在这里,会话被实现为非粘性的(意味着,每个请求都可以转到集群中的任何服务器,这与Apache提供的Tomcat集群设置不同。) 请求会话将立即存储到Redis中(会话属性必须是可序列化的),以供其他服务器使用。 当...
3-8Tomcat请求容器中的处理与启动过程源码实现(1).mp4
3-8Tomcat请求容器中的处理与启动过程源码实现(2).mp4
Tomcat初始化流程分析,Tomcat启动流程分析 Tomcat处理一次请求过程分析 servlet初始化流程
对 NIO 模式,请求的流程描述的很详细。值得去仔细的研究。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以...最新的源码供研究
NULL 博文链接:https://yjhexy.iteye.com/blog/661491
1.web.xml内容修改,添加servlet标签 2.添加Servlet接口与实现 3.解析web.xml 4.修改启动时逻辑,扫描全部servlet 5.Request、Response 说明 6.动态处理请求,通过反射创建Servlet 7.浏览器测试
资源是关于tomcat深入剖析的源码. 本书深入剖析Tomcat 4和Tomcat 5中的每个组件,并揭示其内部工作原理。通过学习本书,你将可以自行开发Tomcat组件,或者扩展已有的组件。 Tomcat是目前比较流行的Web服务器之一。...
requestProcess.pdf-Tomcat请求处理流程序列图(2014.10.28-2014.10.29) 架构/-Tomcat服务器的架构结构和设计(2014.10.29-2014.10.29) server.xml-Tomcat容器配置文件(2014.10.29-) config /-Tomcat配置引用...
NULL 博文链接:https://liudeh-009.iteye.com/blog/1563948
Tomcat是一款servlet服务器,它能够接受请求,处理请求并给出响应。
java雷电飞机源码 http服务&ajax编程,请求和响应信息解析,json数据格式 1. 服务器 通俗的讲,能够提供某种服务的机器(计算机)称为服务器 1.2 服务器软件 使计算机能提供某种服务的应用软件,称之为服务器软件. ...
https原理及tomcat配置https方法;SSL加密传输;请求路径https://...;客户端需安装证书...