- 浏览: 27059 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
yukang1:
大哥 好想要源码. 你的代码不全啊 我的亲哥啊
使用纯java ssh方式连接linux服务器,并用此方式部署war到linux的tomcat下
一, tomcat 处理请求的组件 Engine Host Context 和 Wrapper 这四个 分别对应的实现类StnadardEngine,StandardHost,StandardContext和StandardWrapper
Engine:代表tomcat的引擎,可以有多个引擎,他与Connector连接器并列 起到请求与虚拟机主机下对应应用程序的定位。
Host:代表一个虚拟主机,各Host的name不能相同,appBase代表各虚拟主机的应用发布位置;
Context:代表一个应用,Context可以根据应用的/WEB-INF/web.xml文件中定义的servlet来处理请求。一个Host下可以有多个Context;
Wrapper: 代表一个Servlet或者jsp,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。
二,请求在这些容器之间的流转又是通过管道Pipeline 管道是由他们父类容器ContainerBase来控制的, 而管道中流转的是Value这样的东西,而每个容器的都实现了自己的值分别是StandardEngineValue,StandardHostValue,
StandardContextValue和StandardWrapperValue
下面请看从配适器CoyoteAdapter中已经 初步封装的请求 ,如图Service方法
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception { Request request = (Request) req.getNote(ADAPTER_NOTES); Response response = (Response) res.getNote(ADAPTER_NOTES); if (request == null) { // Create objects request = connector.createRequest(); request.setCoyoteRequest(req); response = connector.createResponse(); response.setCoyoteResponse(res); // Link objects request.setResponse(response); response.setRequest(request); // Set as notes req.setNote(ADAPTER_NOTES, request); res.setNote(ADAPTER_NOTES, response); // Set query string encoding req.getParameters().setQueryStringEncoding (connector.getURIEncoding()); } if (connector.getXpoweredBy()) { response.addHeader("X-Powered-By", POWERED_BY); } boolean comet = false; boolean async = false; try { // Parse and set Catalina and configuration specific // request parameters req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName()); boolean postParseSuccess = postParseRequest(req, request, res, response); if (postParseSuccess) { //check valves if we support async request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported()); // Calling the container的first其实就是StandardEngineValve这么一个类 connector.getService().getContainer().getPipeline().getFirst().invoke(request, response); //代码省略
重点看这句话代码
connector.getService().getContainer().getPipeline().getFirst().invoke(xxx,xxx)
由于connector找到父类Service容器 然后找到处理请求的一组容器的顶级容器 即Engine 这个容器管道 此管道中流转的就是StandardEngineValue这样的即getFirst()方法调用得到
交给此Value值处理(invoke)
下面是 StandardEngineValue方法中invoke
@Override public final void invoke(Request request, Response response) throws IOException, ServletException { // Select the Host to be used for this Request Host host = request.getHost(); if (host == null) { response.sendError (HttpServletResponse.SC_BAD_REQUEST, sm.getString("standardEngine.noHost", request.getServerName())); return; } if (request.isAsyncSupported()) { request.setAsyncSupported(host.getPipeline().isAsyncSupported()); } // Ask this Host to process this request host.getPipeline().getFirst().invoke(request, response); }
也是用了同样的代码
host.getPipeline().getFirst().invoke(request, response);
继续StandardHostValue 一直到 StandardWrapperValue的invoke方法
@Override public final void invoke(Request request, Response response) throws IOException, ServletException { // Initialize local variables we may need boolean unavailable = false; Throwable throwable = null; // This should be a Request attribute... long t1=System.currentTimeMillis(); requestCount++; StandardWrapper wrapper = (StandardWrapper) getContainer(); Servlet servlet = null; Context context = (Context) wrapper.getParent(); // Check for the application being marked unavailable if (!context.getState().isAvailable()) { response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardContext.isUnavailable")); unavailable = true; } // Check for the servlet being marked unavailable 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; } // Allocate a servlet instance to process this request try { if (!unavailable) { //加载实例化Servlet实例 (init(ServletConfig config)方法也被初始化了) //可以看出Servlet是单例的 servlet = wrapper.allocate(); } // 省略代码 ...
接着StandardWrapper的allocate()的方法 查看servlet的创建过程
代码如下
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(); if (!singleThreadModel) { // For non-STM, increment here to prevent a race // condition with unload. Bug 43683, test case // #3 newInstance = true; countAllocated.incrementAndGet(); } } catch (ServletException e) { throw e; } catch (Throwable e) { ExceptionUtils.handleThrowable(e); throw new ServletException (sm.getString("standardWrapper.allocate"), e); } } } } if (!instanceInitialized) { //实例化Servlet initServlet(instance); } if (singleThreadModel) { if (newInstance) { // Have to do this outside of the sync above to prevent a // possible deadlock synchronized (instancePool) { instancePool.push(instance); nInstances++; } } } else { 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); } } 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) { ExceptionUtils.handleThrowable(e); throw new ServletException (sm.getString("standardWrapper.allocate"), e); } } else { try { instancePool.wait(); } catch (InterruptedException e) { // Ignore } } } if (log.isTraceEnabled()) log.trace(" Returning allocated STM instance"); countAllocated.incrementAndGet(); return instancePool.pop(); } }
上述代码可知
1,对于没有实现SingleThreadModel 会确保只有一个instance实例 也就是单个servlet实例
即每次请求都访问同一servlet
2, 如果servlet实现了该接口,会确保不会有两个线程同时执行servlet的service方法。 servlet容器通过同步化访问servlet的单实例来保证,也可以通过维持servlet的实例池,对于新的请求会分配给一个空闲的servlet。
3,注意:SingleThreadModel不会解决所有的线程安全隐患。 例如,会话属性和静态变量仍然可以被多线程的多请求同时访问,即便使用了SingleThreadModel servlet。建议开发人员应当采取其他手段来解决这些问题,而不是实现该接口,比如 避免实例变量的使用或者在访问资源时同步代码块。
发表评论
-
tomcat源码研究之参数编码格式处理
2017-06-09 11:33 1007一,我们知道tomcat作为web服务器以后,我们编写的Se ... -
tomcat源码研究之 web.xml中load-on-startup标签的含义
2017-06-08 14:35 1121(1) 在servlet的配置当中,<load-o ... -
tomcat 源码研究之自定义应用工程jar包加载路径
2017-06-05 09:50 1927tomcat 启动应用工程的时候,它会加载应用工程中的jar ... -
tomcat 源码研究之war工程解析
2017-05-27 16:46 2509我们知道tomcat启动 会带动我们自己的应用工程运 ... -
tomcat 源码研究之http报文解析
2017-05-18 11:30 4756一,我们知道tomcat作为web服务器 已经在行业中应用多年 ... -
tomcat源码研究之测试用例研究
2016-12-17 18:04 666tomcat 作为应用型服务器,尤其是web服务器。我们一般 ...
相关推荐
源码解析部分则是对Tomcat源码的深度剖析,涵盖了关键类和方法的作用、设计模式的运用以及性能优化技巧。这有助于开发者理解Tomcat内部的工作流程,例如,如何处理HTTP请求的生命周期,以及线程池是如何调度和管理的...
在深入探讨Tomcat源码学习之前,我们首先要理解Tomcat是什么。Tomcat是一款开源的、免费的Web服务器和Servlet容器,由Apache软件基金会维护。它实现了Java Servlet和JavaServer Pages(JSP)规范,是Java EE应用...
《深入理解Tomcat:工作原理与源码剖析》 Tomcat作为一款开源的Java Servlet容器,是Apache软件基金会Jakarta项目的重要组成部分,广泛应用于各种Java Web应用的部署。本篇文章将深入探讨Tomcat的工作原理,并结合...
深入学习Java源码有助于理解其内部工作原理,包括类加载、内存管理、垃圾回收、多线程、异常处理等机制。你可以通过阅读和分析Java的OpenJDK源码来探索这些概念,OpenJDK是Java Development Kit(JDK)的一个开源...
【标题】"Tomcat源码资源包"是一个包含Apache Tomcat服务器源代码的压缩文件,旨在帮助开发者深入了解Tomcat的...因此,深入研究像"Tomcat源码资源包"这样的资料,对于Java Web开发者来说是一项非常有价值的学习任务。
- 学习和研究Tomcat如何实现Servlet容器的多线程、线程池、连接管理和内存管理等高级特性。 - 针对特定需求,开发自定义的Valve(管道组件),Connector,Realm(认证模块)等。 总的来说,Tomcat7.0.42的源码为...
2. **线程模型**:Tomcat使用了多线程模型来处理并发请求。源码中的`Catalina`和` Coyote`组件涉及到了这部分内容,包括Acceptor线程和Worker线程的管理。 3. **生命周期管理**:每个Tomcat组件都有自己的生命周期...
《深入剖析Tomcat7源码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用服务器标准,尤其是Servlet和JSP规范。...下载并研究Tomcat7源码,对于提升Java Web开发技能大有裨益。
通过对Tomcat源码的深入研究,我们可以更好地理解和优化Java Web应用的性能,解决运行时问题,并为自定义扩展打下基础。这份研读笔记将是你理解Tomcat工作机制的宝贵参考资料。在阅读源码的过程中,应结合实际应用...
【标题】"简单的Tomcat源码实现"涵盖了Tomcat服务器的基础构建和运行原理,这是一个针对初学者或希望深入了解Tomcat内部工作...对于想要从底层了解Web服务器运作的人来说,研究Tomcat源码无疑是一次宝贵的实践经历。
通过研究Tomcat源码,开发者可以学习到Web服务器的设计原则,理解Servlet容器的工作机制,掌握JSP和EL的编译过程,以及网络通信和多线程编程的相关知识。此外,对于那些需要对Tomcat进行性能优化、安全性增强或功能...
《深入剖析Tomcat源码:基于6.0版本》 Tomcat是一款开源的、轻量级的Java Servlet容器,它负责解析HTTP请求并调用Java应用程序。Tomcat 6.0是其历史上的一个重要版本,提供了许多关键特性和改进。通过深入研究其...
在分析源码的过程中,还需要掌握Java多线程、网络编程、I/O流、XML解析等相关知识。使用给定的jar包,你可以使用Ant构建系统编译源码,使用Eclipse JDT进行代码分析,同时借助JAX-RPC和WSDL4J理解Tomcat与Web服务的...
【TOMCAT源码分析(启动框架)】 Tomcat是一款广泛应用的开源Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为Web应用程序提供了运行环境。本篇文章将深入探讨Tomcat的系统框架及其启动流程...
1. **学习价值**:通过阅读Tomcat源码,可以系统地学习到Java语言在实际项目中的应用技巧,特别是对于多线程、网络编程等高级特性有深入的理解。 2. **扩展功能**:开发者可以根据自己的需求对Tomcat进行定制化开发...
总的来说,Tomcat源码研究涉及了网络编程、多线程、XML解析、安全策略等多个领域,深入学习可以帮助我们理解Web服务器的工作机制,提升编程技巧,更好地解决实际开发中的问题。同时,源码研究也能为我们提供定制化...
Tomcat6采用多线程模型处理请求,每个请求都会分配一个工作线程进行处理。这既保证了请求处理的并发性,也避免了线程池过度消耗资源的问题。 六、安全性 Tomcat6支持多种安全认证方式,如Basic认证、Form认证等,并...
【压缩包子文件的文件名称列表】:虽然只有一个名为“tomcat源码包.txt”的文件,通常情况下,一个完整的Tomcat源码包会包含多个目录和数千个源代码文件,如: 1. `catalina`:这是Tomcat的主要组件,包括服务器...