设为首页 收藏本站
查看: 699|回复: 0

[经验分享] TOMCAT .

[复制链接]

尚未签到

发表于 2018-12-1 06:48:44 | 显示全部楼层 |阅读模式
2004-05-21 13:292291人阅读评论(3)收藏举报  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!
  参考:
  
  
  TOMCAT源码分析(启动框架)


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-641713-1-1.html 上篇帖子: tomcat-ANT 下篇帖子: tomcat-linux
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表