servlet与tomcat的关系

  1. Servlet 工作原理解析:https://www.ibm.com/developerworks/cn/java/j-lo-servlet/
  2. JSP九大内置对象的作用和用法总结?http://blog.csdn.net/sona_shi555/article/details/7797068
  3. Servlet简介与Servlet和HttpServlet运行的流程:https://www.cnblogs.com/libingbin/p/5960456.html

servlet是什么?

Servlet是用Java编写的Server端程序,它与协议和平台无关。
Servlet运行于Java-enabled Web Server中。
Java Servlet可以动态地扩展Server的能力,并采用请求-响应模式提供Web服务。
最早支持Servlet技术的是JavaSoft的Java Web Server。
此后,一些其它的基于Java的Web Server开始支持标准的Servlet API。
Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容。

Servlet 与 Servlet 容器的关系

servlet与tomcat的关系_第1张图片
要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力。虽然它们是彼此依存的,但是又相互独立发展,这一切都是为了适应工业化生产的结果。从技术角度来说是为了解耦,通过标准化接口来相互协作。既然接口是连接 Servlet 与 Servlet 容器的关键,那我们就从它们的接口说起。
(1)Context 容器
Tomcat 的容器等级中,Context 容器是直接管理 Servlet 在容器中的包装类 Wrapper,所以 Context 容器如何运行将直接影响 Servlet 的工作方式。

真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程,在 Tomcat 的配置文件中可以很容易发现这一点,如下:

<Context path="/projectOne " docBase="D:\projects\projectOne"
reloadable="true" />

(2)Servlet 容器的启动过程
Tomcat7 也开始支持嵌入式功能,增加了一个【启动类 org.apache.catalina.startup.Tomcat】。创建一个实例对象并调用 start 方法就可以很容易启动 Tomcat,我们还可以通过这个对象来增加和修改 Tomcat 的配置参数,如可以动态增加 Context、Servlet 等。我们就选择 Tomcat7 自带的 examples Web 工程,并看看它是如何加到这个 Context 容器中的。

清单 1:给 Tomcat 增加一个 Web 工程:
Tomcat tomcat = getTomcatInstance(); 
File appDir = new File(getBuildDirectory(), "webapps/examples"); 
tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); 
tomcat.start(); 
ByteChunk res = getUrl("http://localhost:" + getPort() + 
              "/examples/servlets/servlet/HelloWorldExample"); 
assertTrue(res.toString().indexOf("

Hello World!

"
) > 0);

清单 1的代码是创建一个 Tomcat 实例并新增一个 Web 应用,然后启动 Tomcat 并调用其中的一个 HelloWorldExample Servlet,看有没有正确返回预期的数据。

清单 2:Tomcat 的 addWebapp 方法的代码如下:
public Context addWebapp(Host host, String url, String path) { 
       silence(url); 
       Context ctx = new StandardContext(); 
       ctx.setPath( url ); 
       ctx.setDocBase(path); 
       if (defaultRealm == null) { 
           initSimpleAuth(); 
       } 
       ctx.setRealm(defaultRealm); 
       ctx.addLifecycleListener(new DefaultWebXmlListener()); 
       ContextConfig ctxCfg = new ContextConfig(); 
       ctx.addLifecycleListener(ctxCfg); 
       ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML"); 
       if (host == null) { 
           getHost().addChild(ctx); 
       } else { 
           host.addChild(ctx); 
       } 
       return ctx; 
}

添加一个 Web 应用时将会创建一个 StandardContext 容器,并且给这个 Context 容器设置必要的参数(
url 代表这个应用在 Tomcat 中的访问路径;
path 代表这个应用实际的物理路径)
其中最重要的一个配置是 ContextConfig,【ContextConfig监听器】继承了 【LifecycleListener 监听器接口】,它是在调用清单 2 时被加入到 StandardContext 容器中。
当 Context 容器初始化状态设为 init 时,添加在 Context 容器的 Listener 将会被调用。【ContextConfig监听器】将会负责整个 Web 应用配置文件的解析工作。
最后将这个 Context 容器加到父容器 Host 中。

(3)【ContextConfig监听器】的解析工作有哪些?
ContextConfig 的 init 方法将会主要完成以下工作:
1.创建用于解析 xml 配置文件的 contextDigester 对象
1.读取默认 context.xml 配置文件,如果存在解析它
1.读取默认 Host 配置文件,如果存在解析它
1.读取默认 Context 自身的配置文件,如果存在解析它
1.设置 Context 的 DocBase
ContextConfig 的 init 方法完成后,Context 容器的会执行 startInternal 方法,这个方法启动逻辑比较复杂,主要包括如下几个部分:
1.创建读取资源文件的对象
1.创建 ClassLoader 对象
1.设置应用的工作目录
1.启动相关的辅助类如:logger、realm、resources 等
1.修改启动状态,通知感兴趣的观察者(Web 应用的配置)
1.子容器的初始化
1.获取 ServletContext 并设置必要的参数
1.初始化“load on startup”的 Servlet

(4)Web 应用的初始化工作?
应用的初始化主要是要解析 web.xml 文件,这个文件描述了一个 Web 应用的关键信息,也是一个 Web 应用的入口。
【web.xml 文件】中的各个配置项将会被解析成相应的属性保存在 【WebXml 对象】中。
接下去将会将 WebXml 对象中的属性设置到 Context 容器中,这里包括创建 Servlet 对象、filter、listener 等等,这些代码在 WebXml 的 configureContext 方法中。

(5)servlet 与 wrapper 的关系?
Servlet 被 【解析】 和 【包装】 成 【Context 容器中的 StandardWrapper】。
这里有个疑问,为什么要将 Servlet 包装成 StandardWrapper 而不直接是 Servlet 对象。
这里 StandardWrapper 是 Tomcat 容器中的一部分,它具有容器的特征,而 Servlet 为了一个独立的 web 开发标准,不应该强耦合在 Tomcat 中。
servlet与tomcat的关系_第2张图片

Servlet 体系结构

servlet与tomcat的关系_第3张图片
与 Servlet 主动关联的是三个顶层类,分别是 【ServletConfig】、【ServletRequest】 和 【ServletResponse】。这三个类都是通过容器传递给 Servlet 的。
(1)Servlet 的运行模式是一个典型的“握手型的交互式”运行模式。所谓“握手型的交互式”就是两个模块为了交换数据通常都会准备一个【交易场景】,这个场景一直跟随着这个交易过程直到这个交易完成为止。这个交易场景的初始化是根据这次【交易对象指定的参数来】定制的,这些指定参数通常就会是一个【配置类】。
(1)ServletConfig 接口的作用:获取这个 Servlet 的一些【配置类】属性。
(2)【ServletContext顶层类】的作用:是一个描述【交易场景】的【参数集合】即【配置类】。

Tomcat 创建的 Request 和 Response 类

servlet与tomcat的关系_第4张图片
1.Tomcat 一接受到请求首先将会创建 【org.apache.coyote.Request】 和 【org.apache.coyote.Response】,这两个类是 Tomcat 内部使用的描述一次请求和相应的信息类它们是一个轻量级的类,它们作用就是在服务器接收到请求后,经过简单解析将这个请求快速的分配给后续线程去处理,所以它们的对象很小,很容易被 JVM 回收。
2.接下去当交给一个用户线程去处理这个请求时又创建 【org.apache.catalina.connector.Request】 和 【org.apache.catalina.connector.Response】 对象。这两个对象一直穿越整个 Servlet 容器,直到要传给 Servlet。
3.传给 Servlet 的是 Request 和 Response 的【门面类】 【RequestFacade】 和 【RequestFacade】,这里使用【门面模式】的目的——【封装容器中的数据】。

Servlet 如何工作?

当用户从浏览器向服务器发起一个请求,通常会包含如下信息:【http://hostname: port /contextpath/servletpath】。
hostname 和 port 是用来与服务器建立 TCP 连接。
而后面的【/contextpath/servletpath】即【 URL 】才是用来选择服务器中的哪个子容器来服务用户的请求。
Tomcat7.0 中有个映射类【org.apache.tomcat.util.http.mapper】,这个类保存了 Tomcat 的 Container 容器中的所有子容器的信息,
mapper 将会根据这次请求的 hostnane 和 contextpath 将 host 和 context 容器设置到 Request 的 mappingData 属性中。

Session

(1)Session的三种工作方式
1.基于 URL Path Parameter,默认就支持;
1.基于 Cookie,如果你没有修改 Context 容器个 cookies 标识的话,默认也是支持的;
1.基于 SSL,默认不支持,只有 connector.getAttribute(“SSLEnabled”) 为 TRUE 时才支持。
(2)SSL(Secure Sockets Layer 安全套接层)协议,及其继任者TLS(Transport Layer Security传输层安全)协议,是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密,用于保障网络数据传输安全,利用数据加密技术,确保数据在网络传输过程中不会被截取及窃听。SSL协议已成为全球化标准,所有主要的浏览器和WEB服务器程序都支持SSL协议,可通过安装SSL证书激活SSL协议。
SSL 证书就是遵守 SSL协议的服务器数字证书,由受信任的证书颁发机构(CA机构),验证服务器身份后颁发,部署在服务器上,具有网站身份验证和加密传输双重功能。
如果是第三种情况的话将会根据 javax.servlet.request.ssl_session 属性值设置 Session ID。
(3)有了 Session ID 服务器端就可以创建 HttpSession 对象了,第一次触发是通过 request. getSession() 方法,如果当前的 Session ID 还没有对应的 HttpSession 对象那么就创建一个新的,并将这个对象加到 org.apache.catalina. Manager 的 sessions 容器中保存,Manager 类将管理所有 Session 的生命周期,Session 过期将被回收,服务器关闭,Session 将被序列化到磁盘等。只要这个 HttpSession 对象存在,用户就可以根据 Session ID 来获取到这个对象,也就达到了状态的保持。
(4)Session 的致命弱点是不容易在多台服务器之间共享。

Servlet 中的 Listener

(1)整个 Tomcat 服务器中 Listener 使用的非常广泛,它是基于【观察者模式】设计的。
Listener 的设计对开发 Servlet 应用程序提供了一种快捷的手段,能够方便的从另一个【纵向维度控制程序和数据】。
(2)目前 Servlet 中提供了 6 种两类事件的观察者接口,它们分别是:
4 个 EventListeners 类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。
这些 Listener 的实现类可以配置在 web.xml 中的 标签中。当然也可以在应用程序中动态添加 Listener,需要注意的是 ServletContextListener 在容器启动之后就不能再添加新的,因为它所监听的事件已经不会再出现。掌握这些 Listener 的使用,能够让我们的程序设计的更加灵活。

你可能感兴趣的:(javaee)