- 浏览: 240368 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
feifei435:
不错的文章,但是有一点忘了提,创建了新的sessionid后, ...
Tomcat的Session管理(一) - Session的生成 -
yangcheng33:
博主你为什么这么棒!!!
Tomcat的Session管理(一) - Session的生成 -
u010323779:
哈哈,非常不错,昨天看了一天源代码,不知从何入手,现在看来您的 ...
Tomcat的Session管理(二) - Session后台处理 -
hdwmp123:
...
Tomcat请求处理(一) -- 服务器端口监听 -
tinguo002:
...
Tomcat的Session管理(一) - Session的生成
请求在Tomcat中传到了CoyoteAdapter的#service()方法中后,就要准备进入Pipeline了,如#service()方法中的这句所示:
connector.getContainer().getPipeline().getFirst().invoke(request, response);
这里的Container是Engine,然后得到它的Pipeline对象,然后得到他的第一个Valve,如果没有配置的话第一个Valve就是Basic的了,这里就是org.apache.catalina.core.StandardEngineValve,最后调用了它的#invoke()方法,源代码如下所示:
这个Valve并没做什么实质性的东西,只是将请求继续传递,当然可以定义自己的Valve实现一些特殊的行为。
还是来继续请求的处理过程,和上边Engine的情况类似,请求这次到了org.apache.catalina.core.StandardHostValve的#invoke()方法,源代码如下所示:
不出意外的,请求下边就到了org.apache.catalina.core.StandardContextValve,源代码如下:
这个Valve重要的是包括了对Listener的调用,最后来看一下Wrapper的Valve调用(org.apache.catalina.core.StandardWrapperValve)。
这段代码的关键点是Servlet实例的构建(servlet = wrapper.allocate();)和Filter Chain的调用(filterChain.doFilter(request.getRequest(), response.getResponse());),具体的还要进入方法内部去仔细看一下。comet方式以后再详细看。
connector.getContainer().getPipeline().getFirst().invoke(request, response);
这里的Container是Engine,然后得到它的Pipeline对象,然后得到他的第一个Valve,如果没有配置的话第一个Valve就是Basic的了,这里就是org.apache.catalina.core.StandardEngineValve,最后调用了它的#invoke()方法,源代码如下所示:
public final void invoke(Request request, Response response) throws IOException, ServletException { // 获得Host对象 Host host = request.getHost(); if (host == null) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString( "standardEngine.noHost", request.getServerName())); return; } // 将请求传递给Host host.getPipeline().getFirst().invoke(request, response); }
这个Valve并没做什么实质性的东西,只是将请求继续传递,当然可以定义自己的Valve实现一些特殊的行为。
还是来继续请求的处理过程,和上边Engine的情况类似,请求这次到了org.apache.catalina.core.StandardHostValve的#invoke()方法,源代码如下所示:
public final void invoke(Request request, Response response) throws IOException, ServletException { // 获得Context对象 Context context = request.getContext(); if (context == null) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm .getString("standardHost.noContext")); return; } // 如果没有设置Loader,那么设置为context自己的ClassLoader if (context.getLoader() != null) { Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader()); } // 将请求通过Pipeline给Context context.getPipeline().getFirst().invoke(request, response); if (Globals.STRICT_SERVLET_COMPLIANCE) { request.getSession(false); } // 处理错误页 response.setSuspended(false); Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR); if (t != null) { throwable(request, response, t); } else { status(request, response); } // 恢复ClassLoader Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader()); }
不出意外的,请求下边就到了org.apache.catalina.core.StandardContextValve,源代码如下:
public final void invoke(Request request, Response response) throws IOException, ServletException { // 不允许请求访问META-INF和WEB-INF文件夹下的内容。 MessageBytes requestPathMB = request.getRequestPathMB(); if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0)) || (requestPathMB.equalsIgnoreCase("/META-INF")) || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0)) || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) { notFound(response); return; } // 如果系统正在重新载入中,那么暂停请求。 boolean reloaded = false; while (context.getPaused()) { reloaded = true; try { Thread.sleep(1000); } catch (InterruptedException e) { ; } } // 如果正在重载,停止老的WebappClassLoader并创建一个新的 if (reloaded && context.getLoader() != null && context.getLoader().getClassLoader() != null) { Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader()); } // 获得Wrapper对象 Wrapper wrapper = request.getWrapper(); if (wrapper == null) { notFound(response); return; } else if (wrapper.isUnavailable()) { wrapper = (Wrapper) container.findChild(wrapper.getName()); if (wrapper == null) { notFound(response); return; } } // 获得Listener列表 Object instances[] = context.getApplicationEventListeners(); ServletRequestEvent event = null; if ((instances != null) && (instances.length > 0)) { event = new ServletRequestEvent(((StandardContext) container).getServletContext(), request.getRequest()); for (int i = 0; i < instances.length; i++) { if (instances[i] == null) continue; if (!(instances[i] instanceof ServletRequestListener)) continue; ServletRequestListener listener = (ServletRequestListener) instances[i]; try { // 调用请求初始化事件 listener.requestInitialized(event); } catch (Throwable t) { container.getLogger().error( sm.getString("standardContext.requestListener.requestInit", instances[i].getClass().getName()), t); ServletRequest sreq = request.getRequest(); sreq.setAttribute(Globals.EXCEPTION_ATTR, t); return; } } } // 调用Wrapper的Valve wrapper.getPipeline().getFirst().invoke(request, response); if ((instances != null) && (instances.length > 0)) { for (int i = 0; i < instances.length; i++) { if (instances[i] == null) continue; if (!(instances[i] instanceof ServletRequestListener)) continue; ServletRequestListener listener = (ServletRequestListener) instances[i]; try { // 调用请求结束事件 listener.requestDestroyed(event); } catch (Throwable t) { container.getLogger().error( sm.getString("standardContext.requestListener.requestDestroy", instances[i].getClass().getName()), t); ServletRequest sreq = request.getRequest(); sreq.setAttribute(Globals.EXCEPTION_ATTR, t); } } } }
这个Valve重要的是包括了对Listener的调用,最后来看一下Wrapper的Valve调用(org.apache.catalina.core.StandardWrapperValve)。
public final void invoke(Request request, Response response) throws IOException, ServletException { boolean unavailable = false; Throwable throwable = null; long t1 = System.currentTimeMillis(); requestCount++; // 获得Wrapper所关联的对象 StandardWrapper wrapper = (StandardWrapper) getContainer(); // Servlet对象 Servlet servlet = null; // 获得Context对象 Context context = (Context) wrapper.getParent(); if (!context.getAvailable()) { response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm .getString("standardContext.isUnavailable")); unavailable = true; } if (!unavailable && wrapper.isUnavailable()) { container.getLogger().info( sm.getString("standardWrapper.isUnavailable", wrapper.getName())); long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString( "standardWrapper.isUnavailable", wrapper.getName())); } else if (available == Long.MAX_VALUE) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString( "standardWrapper.notFound", wrapper.getName())); } unavailable = true; } try { if (!unavailable) { // 分配一个Servelt实例 servlet = wrapper.allocate(); } } catch (UnavailableException e) { container.getLogger().error( sm.getString("standardWrapper.allocateException", wrapper.getName()), e); long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString( "standardWrapper.isUnavailable", wrapper.getName())); } else if (available == Long.MAX_VALUE) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString( "standardWrapper.notFound", wrapper.getName())); } } catch (ServletException e) { container.getLogger().error( sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e)); throwable = e; exception(request, response, e); servlet = null; } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.allocateException", wrapper.getName()), e); throwable = e; exception(request, response, e); servlet = null; } boolean comet = false; if (servlet instanceof CometProcessor && request.getAttribute("org.apache.tomcat.comet.support") == Boolean.TRUE) { comet = true; request.setComet(true); } // 告知Request已经收到 try { response.sendAcknowledgement(); } catch (IOException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().warn( sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e); throwable = e; exception(request, response, e); } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e); throwable = e; exception(request, response, e); servlet = null; } MessageBytes requestPathMB = null; if (request != null) { requestPathMB = request.getRequestPathMB(); } request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR, ApplicationFilterFactory.REQUEST_INTEGER); request.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB); // 创建FilterChain ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance(); ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet); request.setComet(false); try { // web.xml中的<jsp-file>标签 String jspFile = wrapper.getJspFile(); if (jspFile != null) request.setAttribute(Globals.JSP_FILE_ATTR, jspFile); else request.removeAttribute(Globals.JSP_FILE_ATTR); // 调用Filter if ((servlet != null) && (filterChain != null)) { if (context.getSwallowOutput()) { try { SystemLogHandler.startCapture(); if (comet) { filterChain.doFilterEvent(request.getEvent()); request.setComet(true); } else { filterChain.doFilter(request.getRequest(), response.getResponse()); } } finally { String log = SystemLogHandler.stopCapture(); if (log != null && log.length() > 0) { context.getLogger().info(log); } } } else { if (comet) { request.setComet(true); filterChain.doFilterEvent(request.getEvent()); } else { filterChain.doFilter(request.getRequest(), response.getResponse()); } } } request.removeAttribute(Globals.JSP_FILE_ATTR); } catch (ClientAbortException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); throwable = e; exception(request, response, e); } catch (IOException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), e); throwable = e; exception(request, response, e); } catch (UnavailableException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), e); wrapper.unavailable(e); long available = wrapper.getAvailable(); if ((available > 0L) && (available < Long.MAX_VALUE)) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString( "standardWrapper.isUnavailable", wrapper.getName())); } else if (available == Long.MAX_VALUE) { response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString( "standardWrapper.notFound", wrapper.getName())); } } catch (ServletException e) { request.removeAttribute(Globals.JSP_FILE_ATTR); Throwable rootCause = StandardWrapper.getRootCause(e); if (!(rootCause instanceof ClientAbortException)) { container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), rootCause); } throwable = e; exception(request, response, e); } catch (Throwable e) { request.removeAttribute(Globals.JSP_FILE_ATTR); container.getLogger().error( sm.getString("standardWrapper.serviceException", wrapper.getName()), e); throwable = e; exception(request, response, e); } if (filterChain != null) { if (request.isComet()) { filterChain.reuse(); } else { filterChain.release(); } } // 释放Servlet对象 try { if (servlet != null) { wrapper.deallocate(servlet); } } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.deallocateException", wrapper.getName()), e); if (throwable == null) { throwable = e; exception(request, response, e); } } try { if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) { wrapper.unload(); } } catch (Throwable e) { container.getLogger().error( sm.getString("standardWrapper.unloadException", wrapper.getName()), e); if (throwable == null) { throwable = e; exception(request, response, e); } } long t2 = System.currentTimeMillis(); long time = t2 - t1; processingTime += time; if (time > maxTime) maxTime = time; if (time < minTime) minTime = time; }
这段代码的关键点是Servlet实例的构建(servlet = wrapper.allocate();)和Filter Chain的调用(filterChain.doFilter(request.getRequest(), response.getResponse());),具体的还要进入方法内部去仔细看一下。comet方式以后再详细看。
发表评论
-
Tomcat NIO源代码分析(三) -- Protocol和Processor
2010-12-09 09:39 2971现在请求到了Protocol(Http11NioProtoco ... -
Tomcat NIO源代码分析(二) -- Poller
2010-12-08 08:46 4476接着上面的流程,现在请求到了Poller的#register( ... -
Tomcat NIO源代码分析(一) -- Acceptor
2010-12-07 09:11 6774这里主要讲一下Tomcat使用NIO启动和进行请求处理的大致流 ... -
Tomcat的Session管理(二) - Session后台处理
2009-01-06 18:57 10981Tomcat会开启一个后台线程每隔一段时间检查Session的 ... -
Tomcat的Session管理(一) - Session的生成
2009-01-06 17:03 38248Session对象的创建一般是源于这样的一条语句: Sess ... -
Tomcat请求处理(七) - Servlet实例的调用
2009-01-05 17:09 5451Tomcat请求处理中Servlet实例的调用是和Filter ... -
Tomcat请求处理(六) -- Servlet实例创建
2009-01-04 19:02 4845首先,来看一下Servlet的载入过程。 具体是在org.a ... -
Tomcat请求处理(四) -- Request, Response, 和Pipeline
2008-12-25 18:24 35251. Request和Response 当处理请求的时候,T ... -
Tomcat请求处理(三) -- coyote请求处理
2008-12-19 00:51 6112在上一篇文章文章中,Tomcat的请求处理到了JIoEndpo ... -
Tomcat请求处理(二) -- 请求处理框架
2008-11-03 10:05 3793书接上文。 当Tomcat的Acceptor监听到有请求到来 ... -
Tomcat请求处理(一) -- 服务器端口监听
2008-10-31 15:14 6761其实tomcat在哪个类中监听请求的代码很容易找到: 在or ... -
Tomcat启动部分源代码分析(五) -- 应用程序加载
2008-10-30 19:10 2456前面所叙述的tomcat启动中并没有webapps下边应用程序 ... -
Tomcat启动部分源代码分析(四) -- 开启容器
2008-10-28 12:23 2297四. 开启容器 最后是Bootstrap#start()方法 ... -
Tomcat启动部分源代码分析(三) -- 载入
2008-10-28 12:21 3040二. 载入 2. Bootstrap的#Bootstrap# ... -
Tomcat启动部分源代码分析(二) -- 初始化
2008-10-28 12:17 5439二. 初始化 1. 首先是Boo ... -
Tomcat启动部分源代码分析(一) -- 概览
2008-10-28 12:10 3735一. 概览 本文所涉及的Tomcat为6.0版本。 Tom ...
相关推荐
tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-...
解决tomcat8-maven-plugin-3.0-r1655215.jar阿里云同有的问题。放到路径org\apache\tomcat\maven\tomcat8-maven-plugin\3.0-r1655215\就可以了
开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-windows-x86开发工具 apache-tomcat-8.0.41-...
tomcat6-dta-ssl-1.0.0.jar 此类文件将有助于tomcat支持ssl协议
tomcat9负载均衡tomcat-cluster-redis-session-manager_4.0
apache-tomcat-8.5.20.tar.gz源码包和context.xml文件,这套配置是我自己亲测可用的。。另外我用的redis4这个版本。注意:如果你使用的TOMCAT其他版本。例如tomcat6或者7这套JAR包可能不可用,tomcat8.0没有测试。...
Maven使用tomcat8-maven-plugin插件
文件名写错了,此压缩文件支持tomcat8.5。是否支持8.0请自行测试,本人只测试了8.5,可以使用。压缩文件包括tomcat-redis-session-manager-...apache-tomcat-8.5.33.tar.gz,nginx-1.6.2.tar.gz也打包进去,一步到位。
修改版tomcat7-maven-plugin-2.2.jar
Tomcat8亲测可用 tomcat-redis-session-manager的jar包 修改了tomcat-redis-session-manager源码进行的编译生成的jar包
tomcat-redis-session-manager-2.0.0.jar
用于配置 tomcat-redis-session-manager
tomcat-juli.jar和tomcat-juli-adapters.jar tomcat-juli.jar和tomcat-juli-adapters.jar
tomcat-embed-core-8.5.23.jar
tomcat6-maven-plugin-2.1插件包
使用tomcat-redis-session-manager进行统一session管理所需jar包,包括tomcat6-jdk6、tomcat7-jdk7、tomcat8-jdk8
apache-tomcat-8.0.41-windows-x64 tomcat8最新稳定版, 亲测可用
apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-tomcat-9.0.45-windows-x64apache-...
maven-tomcat-plugin让maven与tomcat配合得很好。它可以把应用部署到Tomcat服务器,也可以把tomcat作为内嵌服务器启动,就像jetty一样。 使用JPDA启动tomcat的远程调试功能。这样就能与eclipse配合起来,轻松地实现...