Servlet 是运行在Web服务器的Java小程序。Servlet可以获取并针对Web客户端的请求作出响应。一般情况下,通过HTTP,即超文本传输协议,进行传输通信。
tomcat是什么?
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的核心架构图

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.1Connector 组件
Connector 组件是 Tomcat 中两个核心组件之一,它的主要任务是负责接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和 Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求并把产生的 Request 和 Response 对象传给处理这个请求的线程,处理这个请求的线程就是 Container 组件要做的事了
于这个过程比较复杂,大体的流程可以用下面的顺序图来解释:

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

从上图可以看出 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一生中只有一个实例出现,但是有多个线程出现。
加载类 Servlet .class文件
实例化 构造函数运行
初始化 容器调用 init() 方法(一生只调一次,并且是在第一次调用servlet的 时候执行)
service方法 servlet一生主要在这里度过
销 毁 销毁实例之前调用 destroy() 方法
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.youkuaiyun.com/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