- 浏览: 1357806 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (453)
- Struts2 (4)
- Struts1 (16)
- Spring (9)
- Hibernate (5)
- AJAX (16)
- MS Server (9)
- Oracle (35)
- 测试技术 (5)
- 其他 (37)
- JSF (1)
- EJB (5)
- ASP.NET (9)
- iBATIS (5)
- Struts Spring Hibernate (2)
- HTML (12)
- Eclipse使用 (5)
- 设计模式 (5)
- JSP (32)
- 正则表达式 (2)
- 服务器 (12)
- Java基础 (48)
- MySQL (4)
- 面试 (22)
- UML (1)
- 数据结构 (3)
- Ant (2)
- 规范 (4)
- JavaScript (29)
- 软件使用及技巧 (25)
- PHP (1)
- DWR (3)
- FreeMarker (1)
- ExtJs (17)
- JFreeChart (9)
- Reports (2)
- JavaException (1)
- Java Mail (1)
- Flex (9)
- 异常 (12)
- Log4j (2)
- WebService (1)
- jQuery (1)
- Sybase (2)
- myeclipse_plugin (2)
- Linux (5)
- jbpm (2)
- SCM (1)
- mongoDB (1)
最新评论
-
lihua2008love:
<typeAlias alias="User& ...
IBATIS简单操作 -
lihua2008love:
...
关于项目框架设计的一点学习 -
c_jinglin:
我使用<OBJECT CLASSID="cls ...
这就是个静态页面通过js控制mscomm对某com设备进行访问的例子. -
zlbjava:
赞,用了还不错
java获取请求的ip地址,并解析ip所属地区 -
完美天龙:
cs842813290 写道楼主,我明白的地方:在链表已有N个 ...
JAVA实现双向链表
0:前言
我们知道了tomcat的整体框架了, 也明白了里面都有些什么组件, 以及各个组件是干什么用的了。
http://www.csdn.net/Develop/read_article.asp?id=27225
我想,接下来我们应该去了解一下 tomcat 是如何处理jsp和servlet请求的。
1. 我们以一个具体的例子,来跟踪 TOMCAT , 看看它是如何把 Request 一层一层地递交给下一个容器, 并最后交给 Wrapper 来处理的。
以 http://localhost:8080/web/login.jsp 为例子
(以下例子, 都是以 tomcat4 源码为参考)
这篇心得主要分为3个部分: 前期, 中期, 和末期。
前期:讲解了在浏览器里面输入一个URL,是怎么被tomcat抓住的。
中期:讲解了被tomcat抓住后,又是怎么在各个容器里面穿梭, 最后到达最后的处理地点。
末期:讲解到达最后的处理地点后,又是怎么具体处理的。
2 、 前期 Request的born.
在这里我先简单讲一下request这个东西。
我们先看着这个URL: http://localhost:8080/web/login.jsp 它是动用了8080端口来进行socket通讯的。
我们知道, 通过
InputStream in = socket.getInputStream() 和
OutputStream out = socket.getOutputStream()
就可以实现消息的来来往往了。
但是如果把Stream给应用层看,显然操作起来不方便。
所以,在tomcat 的Connector里面, socket被封装成了Request和Response这两个对象。
我们可以简单地把Request看成管发到服务器来的数据,把Response看成想发出服务器的数据。
但是这样又有其他问题了啊? Request这个对象是把socket封装起来了, 但是他提供的又东西太多了。
诸如Request.getAuthorization(), Request.getSocket()。 像 Authorization这种东西开发人员拿来基本上用不太着,而像socket这种东西,暴露给开发人员又有潜在的危险。 而且啊, 在Servlet Specification里面标准的通信类是ServletRequest和HttpServletRequest,而非这个Request类。 So, So, So. Tomcat必须得捣持捣持Request才行。 最后tomcat选择了使用捣持模式(应该叫适配器模式)来解决这个问题。它把org.apache.catalina.Request 捣持成了 org.apache.coyote.tomcat4.CoyoteRequest。 而CoyoteRequest又实现了ServletRequest和HttpServletRequest 这两种接口。 这样就提供给开发人员需要且刚刚需要的方法了。
ok, 让 我们在 tomcat的顶层容器 - StandardEngin 的invoke()方法这里设置一个断点, 然后访问
http://localhost:8080/web/login.jsp , 我们来看看在前期都会路过哪些地方:
1. run(): 536, java.lang.Thread, Thread.java
CurrentThread
2. run():666, org.apache.tomcat.util.threads.ThreadPool$ControlRunnable, ThreadPool.java
ThreadPool
3. runIt():589, org.apache.tomcat.util.net.TcpWorkerThread, PoolTcpEndpoint.java
ThreadWorker
4. processConnection(): 549
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler, Http11Protocol.java
http protocol parser
5. Process(): 781, org.apache.coyote.http11.Http11Processor, Http11Processor.java
http request processor
6. service(): 193, org.apache.coyote.tomcat4.CoyoteAdapter,CoyoteAdapter.java
adapter
7. invoke(): 995, org.apache.catalina.core.ContainerBase, ContainerBase.java
StandardEngin
1. 主线程
2. 启动线程池.
3. 调出线程池里面空闲的工作线程。
4. 把8080端口传过来由httpd协议封装的数据,解析成Request和Response对象。
5. 使用 Http11Processor 来处理request
6. 在 Http11Processor 里面, 又会call CoyoteAdapter 来进行适配处理,把Request适配成实现了ServletRequest和HttpServletRequest接口的 CoyoteRequest.
7 . 到了这里,前期的去毛拔皮工作就基本上搞定,可以交给 StandardEngin 做核心的处理工作了。
3. 中期。 在各个容器间的穿梭。
Request在各个容器里面的穿梭大致是这样一种方式:
每个容器里面都有一个管道(pipline), 专门用来传送Request用的。
管道里面又有好几个阀门(valve), 专门用来过滤Request用的。
在管道的低部通常都会放上一个默认的阀们。 这个阀们至少会做一件事情,就是把Request交给子容器。
让我们来想象一下:
当一个Request进入一个容器后, 它就在管道里面流动,波罗~ 波罗~ 波罗~ 地穿过各个阀门。在流到最后一个阀门的时候,吧唧~ 那个该死的阀门就把它扔给了子容器。 然后又开始 波罗~ 波罗~ 波罗~ ... 吧唧~.... 波罗~ 波罗~ 波罗~ ....吧唧~....
就是通过这种方式, Request 走完了所有的容器。( 感觉有点像消化系统,最后一个地方有点像那里~ )
OK, 让我们具体看看都有些什么容器, 各个容器里面又都有些什么阀门,这些阀们都对我们的Request做了些什么吧:
3.1 StandardEngin 的pipeline里面放的是: StandardEnginValve
在这里, VALVE 做了三件事:
1. 验证传递过来的 request 是不是 httpservletRequest.
2 验证传递过来的 request 是否携带了 host header 信息 .
3 选择相应的 host 去处理它。(一般我们都只有一个host: localhost ,也就是 127.0.0.1 )。
到了这个地方, 我们的 request 就已经完成了在 Engin 这个部分的历史使命, 通向前途未卜的下一站: host 了。
3.2 StandardHost 的pipline里面放的是: StandardHostValve
1. 验证传递过来的 request 是不是 httpservletRequest.
2. 根据 Request 来确定哪个 Context 来处理。
Context 其实就是 webapp , 比如 http://localhost:8080/web/login.jsp
这里 web 就是 Context 罗!
3. 既然确定了是哪个 Context 了,那么就应该把那个 Context 的 classloader 付给当前线程了。
Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
这样 request 就只看得见指定的 context 下面的 classes 啊, jar 啊这些, 而看不见 tomcat 本身的类, 什么 Engin 啊, Valve 啊。 不然还得了啊!
4. 既然request到了这里了,看来用户是准备访问web这个web app了,咋们得更新一下这个用户的session不是! Ok , 就由manager更新一下用户的session信息
5. 交给具体的Context 容器去继续处理Request.
6. Context处理完毕了,把 classloader 还回来。
3.3 StandardContext 的pipline里面放的是: StandardContextValve
1. 验证传递过来的 request 是不是 httpservletRequest.
2. 如果 request 意图不轨,想要访问 /meta-inf, /web-inf 这些目录下的东西,呵呵,没有用D!
3. 这个时候就会根据 Request 到底是 Servlet , 还是 jsp , 还是静态资源来决定到底用哪种 Wrapper 来处理这个 Reqeust 了。
4. 一旦决定了到底用哪种 Wrapper , OK ,交给那个 Wrapper 处理。
4. 末期。 不同的需求是怎么处理的.
StandardWrapper
之前对Wrapper没有做过讲解,其实它是这样一种东西。
我们在处理Request的时候,可以分成3种。
处理静态的: org.apache.catalina.servlets.DefaultServlet
处理jsp的: org.apache.jasper.servlet.JspServlet
处理servlet的: org.apache.catalina.servlets.InvokerServlet
不同的request就用这3种不同的servlet去处理。
Wrapper就是对它们的一种简单的封装,有了Wrapper后,我们就可以轻松地拦截每次的Request。也可以容易地调用servlet的init()和destroy()方法, 便于管理嘛!
具体情况是这么滴:
如果request是找jsp文件,StandardWrapper里面就会封装一个org.apache.jasper.servlet.JspServlet去处理它。
如果request是找 静态资源 ,StandardWrapper里面就会封装一个org.apache.jasper.servlet.DefaultServlet 去处理它。
如果request是找servlet ,StandardWrapper里面就会封装一个org.apache.jasper.servlet.InvokerServlet 去处理它。
StandardWrapper同样也是容器,既然是容器, 那么里面一定留了一个管道给request去穿,管道低部肯定也有一个阀门(注1),用来做最后一道拦截工作.
在这最底部的阀门里,其实就主要做了两件事:
一是启动过滤器,让request在N个过滤器里面筛一通,如果OK! 那就PASS。 否则就跳到其他地方去了。
二是servlet.service((HttpServletRequest) request,(HttpServletResponse) response); 这个方法.
如果是 JspServlet, 那么先把jsp文件编译成servlet_xxx, 再invoke servlet_xxx的servie()方法。
如果是 DefaultServlet, 就直接找到静态资源,取出内容, 发送出去。
如果是 InvokerServlet, 就调用那个具体的servlet的service()方法。
ok! 完毕。
注1: StandardWrapper 里面的阀门是最后一道关口了。 如果这个阀门欲意把request交给StandardWrapper 的子容器处理。 对不起, 在设计考虑的时候, Wrapper就被考虑成最末的一个容器, 压根儿就不会给Wrapper添加子容器的机会! 如果硬是要调用addChild(), 立马抛出IllegalArgumentException!
参考:
<
http://jakarta.apache.org/tomcat/
>
<
http://www.onjava.com/pub/a/onjava/2003/05/14/java_webserver.html
>
发表评论
-
apache下二级域名实现的精简配置
2009-07-01 13:37 1609在我最近给《商业网站开放服务平台》项目中,我需要给自动生成的网 ... -
Apache 2.2.x+Tomcat6集群配置备忘
2009-07-01 13:23 1608在我们部署Web应用时,不可避免大多都会涉及到集群问题,此文作 ... -
JProfiler连接Weblogic使用说明
2009-02-17 21:56 2272JProfiler连接Weblogic使用说明http://w ... -
配置myeclipse weblogic10
2009-01-05 12:11 2724安装 WebLogic 比较容易,在这里就不再累述了,大家可以 ... -
JBOSS5.0 安装与配置详解
2009-01-03 09:28 14962一.下载与安装JBoss 在本文中,我下载的JBoss版本为 ... -
tomcat安装windows服务
2008-12-26 10:41 1586在tomcat安装目录\bin\ 执行service.bat ... -
Tomcat6.0.14下配置Tomcat Administration Web Applicati
2008-08-31 22:24 2149Tomcat 5.5 以后的binary 核心安装版不再集成T ... -
有关Tomcat应用程序目录、端口、默认目录、应用程序默认打开文件、使用数据库连接池等方面的配置
2008-05-07 23:26 3147修改Tomcat应用程序目录 修改Tomcat端口 修改T ... -
TOMCAT源码分析(启动框架)
2008-05-07 22:18 1376OMCAT源码分析(启动框架) 前言: 本文是我阅读了T ... -
配置tomcat5.5 jndi 各种配置方式 分析总结(mysql)
2008-04-27 19:52 2354准备工作: 安装tomcat5.5(注意这点) 安装mysql ... -
在myeclipse中配置weblogic
2008-04-27 19:45 1487安装WebLogic8.1 安装WebLogi ...
相关推荐
4. "Tomcat源码分析(4)容器处理链接之责任链模式.doc":分析了Tomcat如何利用责任链模式来处理请求,使得请求可以被多个处理器(如过滤器)有序处理。 5. "tomcat加载类的顺序.doc":详细说明了Tomcat加载类的具体...
《Tomcat6源码分析——深入理解Web服务器的运行机制》 Tomcat6作为Apache软件基金会的Jakarta项目的一部分,是一款广泛使用的Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为开发和部署...
### Tomcat架构的源码分析 #### 一、Tomcat的架构概述 Tomcat作为一款广泛使用的开源Java Servlet容器,其内部架构设计简洁而高效。本文档将对Tomcat的架构进行详细介绍,并从源码层面深入分析其核心组成部分。...
【TOMCAT源码分析(启动框架)】 Tomcat是一款广泛应用的开源Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为Web应用程序提供了运行环境。本篇文章将深入探讨Tomcat的系统框架及其启动流程...
Tomcat源码剖析 : 整体架构 层层分析 源码解析 架构分析 (Http服务器功能:Socket通信(TCP/IP)、解析Http报文 Servlet容器功能:有很多Servlet(自带系统级Servlet+自定义Servlet),Servlet处理具体的业务逻辑...
Apache Tomcat源码分析 Apache Tomcat是一款广泛应用的开源Java Servlet容器,它是Java EE Web应用程序的标准实现。Tomcat源码的深入理解对于Java Web开发者来说是至关重要的,它可以帮助我们了解HTTP服务器的工作...
【标题】"Tomcat源码分析" 在深入探讨Tomcat源码之前,首先需要了解Tomcat是什么。Tomcat是一款开源的、基于Java的Web应用服务器,由Apache软件基金会开发。它实现了Java Servlet和JavaServer Pages(JSP)规范,...
Apache Tomcat 8.5.23 源码分析 Apache Tomcat 是一个开源的、免费的Web服务器和Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,是开发和部署Java Web应用的重要平台。深入理解Tomcat的源码有助...
《Tomcat源码分析1——服务启动与架构详解》 Tomcat,作为一款广泛应用的开源Java Servlet容器,其内部架构和启动流程对于深入理解和优化Web应用程序至关重要。本文将重点解析Tomcat启动时的关键步骤和核心组件,...
《深入理解Tomcat源码分析1:Connector配置详解》 Tomcat,作为广泛使用的Java Servlet容器,其核心组件之一就是Connector,它负责处理Web服务器与客户端之间的通信。本篇文章将详细探讨Tomcat Connector的种类、...
根据所提供的文件信息,我们将从以下几个方面详细探讨Tomcat源码的相关知识点: 1. Catalina脚本解析:Catalina是Tomcat的主引擎,负责整个容器的初始化和处理。在Tomcat源码中,Catalina的脚本解析是了解其启动...
源码分析是提升开发者对服务器内部运作机制理解的重要途径,尤其对于Tomcat这样的核心组件,源码的学习能够帮助我们更深入地理解Web应用的部署、运行以及性能优化。 首先,我们要了解Tomcat的架构。Tomcat7基于...
《深入理解Tomcat源码:必备依赖包解析》 Tomcat作为一款广泛应用的开源Java Servlet容器,其源码的编译与理解对于开发者来说具有重要的价值。为了能够顺利地编译Tomcat源码,了解并掌握相关的依赖包是至关重要的。...
【标题】"Tomcat源码资源包"是一个包含Apache Tomcat服务器源代码的压缩文件,旨在帮助开发者深入了解Tomcat的工作原理以及进行定制化开发。Tomcat是Java Servlet和JavaServer Pages(JSP)的开源应用服务器,是轻量...
Tomcat源码分析有助于识别性能瓶颈,例如调整线程池大小、缓存策略、连接器设置等。此外,了解如何配置和使用NIO或APR(Apache Portable Runtime)连接器可以显著提升Tomcat的并发处理能力。 8. **故障排查** ...
二、Tomcat源码分析 1. **启动流程**:从`bin/catalina.sh`或`bin/catalina.bat`开始,通过`org.apache.catalina.startup.Bootstrap`启动Catalina,加载配置文件,初始化服务器,最后启动主循环监听端口。 2. **...