Servlet工作原理

来源:互联网 发布:淘宝买东西如何开发票 编辑:程序博客网 时间:2024/06/01 19:57

Servlet工作原理

简介

servlet 是运行在 Web 服务器中的小型 Java 程序。因此它的运行必须需要容器的支持。Tomcat 是最常用的 JSP/Servlet 容器。容器管理了Servlet的整个生命周期。

Servlet容器

Tomcat 是最常用的 JSP/Servlet 容器,Tomcat 本身也很复杂,我们只从 Servlet 与 Servlet 容器的接口部分开始介绍。Tomcat 的容器等级中,Context 容器是直接管理 Servlet 在容器中的包装类 Wrapper,所以 Context 容器如何运行将直接影响 Servlet 的工作方式。

Servlet的生命周期

实际上,Tomcat是将Servlet包装成StandardWrapper 并作为子容器添加到 Context 中。但是为了方便理解,暂且就先认为是直接将Servlet添加到Context中的。下面我们简单谈谈Servlet对象生命周期。
1. 加载和实例化:如果Servlet容器还没实例化一个Servlet对象,此时容器装载和实例化一个 Servlet。创建出该 Servlet 类的一个实例。如果已经存在一个Servlet对象,此时不再创建新实例。
2. 初始化: 在产生 Servlet 实例后,容器负责调用该 Servlet 实例的 init() 方法,在处理用户请求之前,来做一些额外的初始化工作。
3. 处理请求:当 Servlet 容器接收到一个 Servlet 请求时,便运行与之对应的 Servlet 实例的 service() 方法,service() 方法根据用户的请求调用相对应的doGet或doPost 方法来处理用户请求。然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。
4. 销毁: 当 Servlet 容器决定将一个 Servlet 从服务器中移除时 ( 如 Servlet 文件被更新或服务器重启 ),便调用该 Servlet 实例的 destroy() 方法。

Servlet的使用

  1. 自定义Servlet一般需要继承HttpServlet,而HttpServlet是继承GenericServlet,而GenericServlet是继承Servlet。
  2. 请求的实际处理者是doGet,doPost方法,自定义Servlet类需要重写doGet,doPost方法。

Servlet的工作流程


1. 当客户端浏览器向服务器请求一个 Servlet 时,服务器收到该请求后,首先到容器中检索与请求匹配的 Servlet 实例是否已经存在。
2. 若不存在,则 Servlet 容器负责加载并实例化出该类 Servlet的一个实例对象,接着容器框架负责调用该实例的 init() 方法来对实例做一些初始化工作,然后Servlet 容器运行该实例的 service() 方法。
3. 若 Servlet 实例已经存在,则容器框架直接调用该实例的 service() 方法。
service() 方法在运行时,自动派遣运行与用户请求相对应的 doXX() 方法来响应用户发起的请求。通常,每个 Servlet 类在容器中只存在一个实例,每当请求到来时,则分配一条线程来处理该请求。在处理请求时:
1. Servlet容器会创建一个请求对象ServletRequst,其中封装了用户请求的信息,以便处理客户端请求,此外还会创建一个响应对象ServletResponse,用于响应客户端请求,想客户端返回数据。
2. 然后Servlet容器把创建好的ServletRequst和ServletResponse对象传给用户所请求的Servlet。
3. Servlet利用ServletResponse包含的数据和自身的业务逻辑处理请求,并把处理好的结果写在ServletResponse中,最后Servlet容器把响应结果传给用户。

服务器是如何检索Servlet的

当用户向浏览器发送一个请求,请求中通常会包含如下信息:http://hostname: port /contextpath/servletpath,hostname 和 port 是用来与服务器建立 TCP 连接,而后面的 URL 才是用来选择服务器中那个子容器服务用户的请求。那服务器是如何根据这个 URL 来达到正确的 Servlet 容器中的呢?Tomcat7.0 中这件事很容易解决,因为这种映射工作有专门一个类来完成的,这个就是 org.apache.tomcat.util.http.mapper,这个类保存了 Tomcat 的 Container 容器中的所有子容器的信息,当 org.apache.catalina.connector. Request 类在进入 Container 容器之前,mapper 将会根据这次请求的 hostnane 和 contextpath 将 host 和 context 容器设置到 Request 的 mappingData 属性中。所以当 Request 进入 Container 容器之前,它要访问那个子容器这时就已经确定了。

关于JSP


JSP 本质是一个 Servlet,它的运行也需要容器的支持。下面我们简单了解下JSP的工作流程。
1. 当浏览器向服务器请求一个JSP页面时,服务器收到该请求后会先检查该JSP文件是否被更新。
2. 如果JSP文件被修改或者是第一个创建时,服务器就会将其翻译成一个Servlet类的java源代码,紧接着编译成class文件装载到Jvm中执行。剩下的过程和Servlet的一致。
3. 如果Jsp文件没有被修改,那么服务器就会直接检索到对应的Servlet对象。然后进行servlet的其它处理。
4. Servlet默认情况下都是在请求的时候才去创建其实例的,Jsp也类似,只有在请求的时候才会翻译成java文件并进行后续操作。

HTTP协议是一种无状态的协议,一次请求对应一次响应。如在一次会话的多次请求之间实现数据的共享?这正是Cookie 和 Session所解决的问题。
1. Cookie的实现原理

Cookie是一种轻量级的容器对象,服务器将会话需要保存的信息存储在Cookie中,每个Cookie对象只能存储一条信息。如果需要保存多条信息,就需要创建多个Cookie对象。然后将这些Cookie对象存入到HttpServletResponse对象中。Connector会对response进行解析,最终将cookie保存的信息写入到响应头的set-cookie属性中。一次请求结束,服务器中关于该请求的所有数据也就消失了,但是数据发送给了浏览器保存下来。当浏览器再次向该服务器发送请求时,就会携带上次接收到的cookie中的信息,服务器也会解析这些信息。从而实现了会话间的数据保持。

  1. Session工作原理


有没有一种当时可以将一次会话的数据保存在服务器上呢?我们很容易想到的是,创建一个容器对象,并且使一次会话中的每次请求可以访问到这个容器对象。这也正是session的基本原理。但是,现在的问题在于,如何保证一次会话中的所有请求都可以 访问到这个session容器对象?第一种方式,就是结合前面所讲的cookie技术,将session容器对象的唯一标识发送给浏览器,浏览器在下一次请求的时候再将其发送给服务器,这样服务器就能根据唯一标识找到session对象了。另外一种方式是通过url重写的方式实现的。在返回用户请求的页面之前,将页面内所有的URL后面全部以get参数的方式加上session标识符。这样用户在收到响应之后,无论点击哪个链接或提交表单,都会在再带上session的标识符,从而就实现了会话的保持。

原创粉丝点击