Servlet生命周期和工作原理

名词解释:

  • web.xml = 部署描述符(Deployment Descriptor )
  • 容器 = Servlet Container/Engine

生命周期

主要有四个过程:init->service->doGet/doPost->destory

第一步:加载和实例化

  1. Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码:
    <loadon-startup>1</loadon-startup>
  2. 在Servlet容器启动后,客户首次向Servlet发送请求
  3. Servlet类文件被更新后,重新装载Servlet

Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化。在Servlet的整个生命周期内,init()方法只被调用一次。

第二步:初始化

实例化后会立马进行初始化,并传递实现ServletConfig接口的对象。也就是执行init方法。在init()方法中,Servlet可以部署描述符中读取配置参数,或者执行任何其他一次性活动。在Servlet的整个生命周期类,init()方法只被调用一次。

第三步:请求处理

初始化后,Servlet就可以接受请求了。
基本方式是执行Servlet接口中的service方法。并把请求和响应对象作为参数传递。当并行的请求到来时,多个service()方法能够同时运行在独立的线程中。
service()方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet()、doPost()、doPut(),doDelete() 等方法。
当然,API也提供了HttpServlet抽象类,其中有doGet、doPost等特殊方法。
注意:任意的容器按照规范必须实现上述几种方法,所以你的代码写在这几个方法中都可以。

第四步:终止服务

容器会在合适的时候销毁某个Servlet对象,这个策略取决于容器的开发者/商。
在容器关闭的时候Servlet对象一定会被销毁。
当1或2发生时,也就是Servlet对象被销毁时,destroy方法会被调用

PS:Servlet的生命(周期)是由容器管理的,换句话说,Servlet程序员不能用代码控制其生命。

工作原理

首先简单解释一下Servlet接收和响应客户请求的过程,首先客户发送一个请求,Servlet是调用service()方法对请求进行响应的,通过源代码可见,service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没有doGet,doPost等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。

每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是上文提到的init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。

Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest,ServletResponse强转为HttpRequest和HttpResponse。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void service(ServletRequest req,ServletResponse res) 
throws ServletException,IOException
{
HttpRequest request;
HttpResponse response;

try
{
req = (HttpRequest)request;
res = (HttpResponse)response;
}catch(ClassCastException e)
{
throw new ServletException("non-HTTP request response");
}
service(request,response);
}

代码的最后调用了HTTPServlet自己的service(request,response)方法,然后根据请求去调用对应的doXXX方法,因为HttpServlet中的doXXX方法都是返回错误信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void doGet(HttpServletRequest res,HttpServletResponse resp)
throws ServletException,IOException
{
String protocol = req.getProtocol();
String msg = IStrings.getString("http.method_get_not_supported");
if(protocol.equals("1.1"))
{
resp.sendError(HttpServletResponse.SC.METHOD.NOT.ALLOWED,msg);
}
esle
{
resp.sendError(HttpServletResponse.SC_BAD_REQUEST,msg);
}
}

所以需要我们在自定义的Servlet中override这些方法!

Servlet响应请求阶段

对于用户到达Servlet的请求,Servlet容器会创建特定于这个请求的ServletRequest对象和ServletResponse对象,然后调用Servlet的service方法。service方法从ServletRequest对象获得客户请求信息,处理该请求,并通过ServletResponse对象向客户返回响应信息。

对于Tomcat来说,它会将传递过来的参数放在一个Hashtable中,该Hashtable的定义是:

1
private Hashtable<String String[]> paramHashStringArray = new Hashtable<String String[]>();

这是一个String–>String[]的键值映射。

HashMap线程不安全的,Hashtable线程安全。

Servlet终止阶段

当WEB应用被终止,或Servlet容器终止运行,或Servlet容器重新装载Servlet新实例时,Servlet容器会先调用Servlet的destroy()方法,在destroy()方法中可以释放掉Servlet所占用的资源。

Servlet何时被创建

  1. 默认情况下,当WEB客户第一次请求访问某个Servlet的时候,WEB容器将创建这个Servlet的实例。

  2. 当web.xml文件中如果元素中指定了子元素时,Servlet容器在启动web服务器时,将按照顺序创建并初始化Servlet对象。

注意:在web.xml文件中,某些Servlet只有元素,没有元素,这样我们无法通过url的方式访问这些Servlet,这种Servlet通常会在元素中配置一个子元素,让容器在启动的时候自动加载这些Servlet并调用init()方法,完成一些全局性的初始化工作。

Web应用何时被启动

  1. 当Servlet容器启动的时候,所有的Web应用都会被启动
  2. 控制器启动web应用

JSP运行原理

当Web服务器上的JSP页面第一次被请求执行时,JSP引擎先将JSP页面文件转译成一个Java文件,即Servlet,Java Servlet是基于服务器端编程的API,用Java Servlet编写的Java程序称为servlet,servlet通过HTML与客户交互。服务器将前面转译成的Java文件编译成字节码文件,再执行这个字节码文件来响应客户的请求。当这个JSP页面再次被请求时,只要该JSP文件没有被改动,JSP引擎就直接调用已装载的Servlet。

JSP工作原理
所有JSP页面,在执行的时候都会被服务器端的JSP引擎转换为Servelet(.java),然后又由JSP引擎调用Java编译器,将Servelet(.java)编译为Class文件(.class),并由Java虚拟机(JVM)解释执行。下面验证这一点:
有一个JSP页面Test.jsp,在浏览器地址栏中输入http://localhost:8080/Test.jsp ,将会出现执行结果。同时在%CATALINA_HOME%/work/Catalina/localhost下多出两个文件:_Test_jsp.java和_Test_jsp.class,他们分别就是Servelet和Class文件

JSP和servlet的运行原理探讨

<%page language=”java”%>在服务器端执行.
客户端用户填写 HTML 表单,发送请求。将请求发送给 服务器端servlet(tomcat是servlet的容器)。 servlet 将该 HTTP 请求转换成一个 MQSeries 消息,并将其放入一个队列。 后端应用程序处理该消息,然后通过消息队列发回一个应答。 servlet 从队列中检索消息,并将其存放在一个 Java Bean 中。 然后 servlet 调用编译过的 Java Server Page(JSP) 并动态生成结果 HTML 页面。 JSP 从 Java Bean 检索出该页面需要的数据,将其合并到 HTML,然后将结果页面发送给客户端。

JSP中的html代码和javascrīpt代码不会在服务器端执行,servlet 调用编译过的 Java Server Page(JSP) ,也就是运行由JSP编译成的class文件(运行的代码包括actionBean,formBean,一般的bean 和内嵌在JSP的Java代码).

一个Web运行程序(网站)可以有多个servlet,一般认为一个action就是一个servlet.

所谓Servlet是指运行在服务器端的Java小程序。用于响应客户端的请求。在默认情况下,Servlet采用一种无状态的请求-响应处理方式。Servlet代码的主要作用是为了增强Java服务器端的功能,它运行在服务器端,用于接收并且处理浏览器客户端发出的请求,该请求是通过配置文件web.xml的相关配置进行转发。也就是说Servlet是一个标准的Java类,它符合Java类的一般规则。和一般的Java类不同之处只是在于Servlet可以处理Http请求。

  1. servlet是持久的。servlet只需Web服务器加载一次,后续又用到这个servlet,就不需要再加载。(所谓加载是指servlet加载进JVM运行)
  2. servlet是与平台无关的。
  3. servlet是可扩展的。

Servlet与JSP的比较

  • 有许多相似之处,都可以生成动态网页。
  • JSP的优点是擅长于网页制作,生成动态页面比较直观,缺点是不容易跟踪与排错。
  • Servlet是纯Java语言,擅长于处理流程和业务逻辑,缺点是生成动态网页不直观。

参考:

赏个包子钱~~