servlet 梳理

 一道题目引发的“servlet和过滤器,监听器,servlet启动顺序是什么样的”,梳理一下,温故知新。
包含以下内容:以 Tomcat 为例了解 Servlet 容器是如何工作的?用户的请求是如何被分配给指定的 Servlet 的? Servlet 容器如何管理 Servlet 生命周期?多线程安全问题?过滤器与监听器顺序?
一背景
上篇笔记整理了tomcat的session机制。偏源码分析。本篇笔记计划以此为开头,为什么呢?因为servlet运行依赖于容器。
servlet是什么?
为了能让Web服务器与Web应用这两个不同的软件系统协作,需要一套标准接口,Servlet就是其中最主要的一个接口。
Servlet 是运行在Web服务器的Java小程序。Servlet可以获取并针对Web客户端的请求作出响应。一般情况下,通过HTTP,即超文本传输协议,进行传输通信。
tomcat是什么?
在Servlet规范中,把能够发布和运行JavaWeb应用的Web服务器称为Servlet容器,他的最主要特称是动态执行JavaWeb应用中的Servlet实现类中的程序代码。 Tomcat是Servlet容器,同时也是轻量级的Web服务器。 这是它的两个身份!

Tomcat作为Web服务器时,主要负责实现HTTP传输等工作。

Tomcat作为Servlet容器时,主要负责解析Request,生成ServletRequest、ServletResponse,将其传给相应的Servlet(调用service( )方法),再将Servlet的相应结果返回。总结一下,tomcat作为servlet容器的作用如下:

1)通信支持。利用容器提供的方法,web服务器能轻松的与servlet进行通信。

2)生命周期管理。容器控制着servlet的生与死。它会负责加载类,实例化,初始化,调用servlet的方法以及使servlet能够被垃圾回收。

3)多线程支持。容器会自动的接受每个servlet请求,创建一个新的java线程。针对每个请求,如果servlet已经运行完相应的HTTP方法,线程就会结束。但是我们同时也得考虑线程的安全性。

4)JSP支持。负责将JSP翻译成真正的java。

下图是tomcat的核心架构图

servlet 梳理 - bohu83 - bohu83的博客

Server,代表整个Servlet容器组件,是Tomcat的顶层元素。其中可以包含一到多个Service;

Service,包含一个Engine,以及一到多个Connector;

Connector,代表和客户端程序实际交互的组件,负责接收客户请求,以及向客户返回响应结果;

Engine,处理同一个Service中所有Connector接收到的客户请求;

Host,在Engine中可以包含多个Host,每个Host定义了一个虚拟主机,它可以包含一个到多个Web应用;

Context,一个Host中可以包含多个Context,每个Context代表了运行在虚拟主机上的单个Web应用。

这些字段都在conf/server.xml中配置。下面分别介绍tomcat的核心组件。

 2  tomcat 核心组件

2.1Connector 组件

Connector 组件是 Tomcat 中两个核心组件之一,它的主要任务是负责接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和 Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求并把产生的 Request 和 Response 对象传给处理这个请求的线程,处理这个请求的线程就是 Container 组件要做的事了

于这个过程比较复杂,大体的流程可以用下面的顺序图来解释:

servlet 梳理 - bohu83 - bohu83的博客

2.2Servlet 容器“Container”

Container 是容器的父接口,所有子容器都必须实现这个接口,Container 容器的设计用的是典型的责任链的设计模式,它有四个子容器组件构成,分别是:Engine、Host、Context、Wrapper,这四个组件不是平行的,而是父子关系,Engine 包含 Host,Host 包含 Context,Context 包含 Wrapper。

servlet 梳理 - bohu83 - bohu83的博客

 从上图可以看出 Tomcat 的容器分为四个等级,真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程。

对应的server.xml格式如下

<Engine defaultHost="localhost" name="Catalina">

    <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
    ………
    <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" 
	    xmlNamespaceAware="false" xmlValidation="false">

        <Valve className="org.apache.catalina.valves.FastCommonAccessLogValve"
            directory="logs"  prefix="localhost_access_log." suffix=".txt"
            pattern="common" resolveHosts="false"/>	   
    …………
    </Host>
</Engine>

StandardEngineValve 和 StandardHostValve 是 Engine 和 Host 的默认的 Valve,它们是最后一个 Valve 负责将请求传给它们的子容器,以继续往下执行。

上面写了当 Connector 接受到一个连接请求时,将请求交给 Container,中间的StandardEngine和StandardHost我们略过,下面看 Context 和 Wrapper 容器时如何处理请求的。下面是处理请求的时序图:

servlet 梳理 - bohu83 - bohu83的博客
结合上图总结一下:
tomcat大概的流程就是启动时 Context  初始化。包括解析 WebXml,并将  WebXml 对象中的属性设置到 Context 容器中,这里包括创建 Servlet 对象、filter、listener 等等。 如果 Servlet 的 load-on-startup 配置项大于 0,那么在 Context 容器启动的时候就会被实例化。 初始化 Servlet 在 StandardWrapper 的 initServlet 方法中,这个方法很简单就是调用 Servlet 的 init 的方法,同时把包装了 StandardWrapper 对象的 StandardWrapperFacade 作为 ServletConfig 传给 Servlet。
对应 Servlet的生命周期

注意他的一生都是由容器控制的。servlet一生中只有一个实例出现,但是有多个线程出现。


加载类   Servlet .class文件

实例化   构造函数运行

初始化    容器调用 init() 方法(一生只调一次,并且是在第一次调用servlet的 时候执行)

service方法    servlet一生主要在这里度过

销 毁           销毁实例之前调用 destroy() 方法

 Servlet 如何工作

当用户从浏览器向服务器发起一个请求,通常会包含如下信息:http://hostname: port /contextpath/servletpath,hostname 和 port 是用来与服务器建立 TCP 连接,而后面的 URL 才是用来选择服务器中那个子容器服务用户的请求。那服务器是如何根据这个 URL 来达到正确的 Servlet 容器中的呢?

  tomcat对这种映射工作有专门一个类来完成的,这个就是 org.apache.tomcat.util.http.mapper,这个类保存了 Tomcat 的 Container 容器中的所有子容器的信息,当 org.apache.catalina.connector. Request 类在进入 Container 容器之前,mapper 将会根据这次请求的 hostnane 和 contextpath 将 host 和 context 容器设置到 Request 的 mappingData 属性中。所以当 Request 进入 Container 容器之前,它要访问那个子容器这时就已经确定了。

 我们现正知道了请求是如何达到正确的 Wrapper 容器,但是请求到达最终的 Servlet 还要完成一些步骤,必须要执行 Filter 链,以及要通知你在 web.xml 中定义的 listener。

接下去就要执行 Servlet 的 service 方法了,通常情况下,我们自己定义的 servlet 并不是直接去实现 javax.servlet.servlet 接口,而是去继承更简单的 HttpServlet 类,service方法根据请求的HTTP方法,来调用doGet()或者doPost()方法。我们在开发servlet时肯定要覆盖此方法。

回答问题:

Servlet过滤器是Servlet的一种特殊的用法,主要用来完成一些通用的操作。(1)、用户认证与授权管理;(2)、统计Web应用的访问量和访问命中率从而形成访问报告;(3)、实现Web应用的日志处理功能;(4)、实现数据压缩功能;(5)、对传输的数据进行加密。 
在程序中使用过滤器主要分两步:(1)、实现java.servlet.Filter的接口;(2)配置Servlet过滤器。

监听器是指对整个WEB环境的监听,当被监听的对象发生情况时,立即调用相应的方法进行处理。Servlet规范中定义了多种类型的 监听器,它们用于监听的事件源分别为ServletContext, HttpSession 和 ServletRequest 这三个域对象。

那如果同一个项目中既存在Listener,又存在Filter,不管它们顺序怎么配置,总是先运行Listener再运行Filter! 

3 总结:

servlet多线程安全问题,不用全局变量。

方法中的局部变量分配在栈空间,每个线程有私有的栈空间。因此访问是线程安全的

待补充一个demo:


但是现在的 web 应用很少有直接将交互全部页面都用 servlet 来实现,而是采用更加高效的 MVC 框架来实现.比如springMVC。待整理专题笔记。

参考:

http://blog.csdn.net/pirateleo/article/details/8574973

http://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/

https://www.ibm.com/developerworks/cn/java/j-lo-servlet/

http://ifeve.com/servlet-study/

http://www.tuicool.com/articles/JnAB7f


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值