`
senton
  • 浏览: 206581 次
  • 性别: Icon_minigender_1
  • 来自: 紫禁城
社区版块
存档分类
最新评论

Servlet的生命周期

阅读更多

Servlet的生命周期

  当 servlet 第一次被创建时,init 方法会被调用。所以你的一次性设置工作的代码应该存在于 init 方法中。用户的请求会导致创建新的线程来调用之前创建的 servlet 实例的 service 方法。并发的多个请求会创建调用service方法的多个线程。同时,你也可以让你的servlet继承一个特殊的接口来保证在任何时间只能有一个线程在运行。Service方法会根据收到的HTTP请求的不同来调用不同的doXxx方法(doGet、doPost等)。最终,服务器会调用destroy方法来卸载servlet。

init方法:
  init 方法只在 servlet 首次被创建时被调用。收到用户请求时并不会调用 init 方法。所以,它常被用来作为一次性初始化的工作。Servlet 会在用户首次调用一个 servlet 的 URL 或是服务器启动之时被创建,这取决于你是否在 Web 服务器中注册了 servlet。当收到第一个用户对于这个 servlet 的请求且这个 servlet 只是正确存在于服务器的特定路径而并未明确注册时,这个 servlet 会被创建。

  init 方法有两个版本:一个没有参数;一个以 ServletConfig 对象作为参数。在 servlet 初始化时不需要任何服务器的设置信息时使用无参数的 init 方法。无参数的 init 方法定义如下:

public void init() throws ServletException {
 // 初始化代码…
}

  当 servlet 需要获得服务器的设置信息才能完成初始化时就要使用 init 的第二个版本。举例来说,servlet 可能需要有关数据库设置、password 文件、服务器特定性能参数点击计数文件、之前请求包含的 serialized cookie 数据等等的信息。这个版本的 init 方法定义如下:

public void init(ServletConfig config) throw ServletException {
 super.init(config);
 //初始化代码…..
}

  这段代码有两个地方需要注意:
  第一,这里的 init 方法有一个 ServletConfig 作为参数。ServletConfig 类提供一个 getInitParameter 方法以便你可以与 servlet 关联的初始化参数。输入(参数名)和输出(参数值)都是 String 类型。需要注意的是初始化参数的设置方法因服务器不同而略有不同。比方我们所熟悉的 Tomcat 中,servlet 的各种属性存放于 web.xml 中;据说WebLogic 应用服务器中我们使用 weblogic.properties 文件来做相同的事情.

  第二个要注意的地方方法体的第一行调用了 super.init,这非常重要!ServletConfig 对象会在servlet的其他地方用到,超类的 init 方法会将 ServletConfig 注册以便 servlet 之后用到。如果你忘了调用 super.init 将会是一件非常头疼的事情。

  核心提示:如果你使用以 ServletConfig 为参数的 init 方法,那么一定要在方法体第一行调用 super.init()。

service方法:
  当服务器接收到对 servlet 的请求时,服务器会产生一个新的线程调用 service 方法。Service 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等)然后相应的调用 doGet、doPost、doPut、doDelete 等方法。如果你的 servlet 处理 POST 请求和 GET 请求方式相同,你也可以尝试覆盖service 方法或者同时实现 doGet 和 doPost 方法。
public void service(HttpServletRequest request,
   HttpServletResponse response) throws
   ServletException, IOException {
 // Servlet 代码
}
这样做并不理想,更好的做法在 doPost 方法中调用 doGet(或者反过来),如下所示。

public void doGet(HttpServletRequest request,
   HttpServletResponse response)
   throws ServletException, IOException {
  // Servlet 代码
}
public void doPost(HttpServletRequest request,
   HttpServletResponse response)
   throws ServletException, IOException {
 doGet(request, response);
}

虽然第二种方法代码稍多了一些,当相比直接覆盖 service 方法它有五个优点:
1. 这样做确保你以后可以在子类中添加对其他请求服务的支持,如 doPut、doTrace 等。如果你你直接覆盖了 service 方法则就没有了这种可能性。
2. 你可以通过实现 getLastModified 方法来增加对修改日期的支持。如果你调用了 doGet 方法,标准 service 方法会用 getLastModified 方法设置 header 的最后修改日期然后对 GET 请求作出响应的回应(包括以修改过的 header,If-Modified-Since header)。
3. 你会自动获得对 HEAD 请求的支持。系统将只返回 doGet 方法设定的 header 和 statu code,而忽略页面体。对于定制 HTTP 客户来说 HEAD 是个很有用的请求方法。例如检查一个页面中的死链时通常使用 HEAD 替代 GET 以减轻服务器负担。
4. 你会自动获得对 OPTIONS 请求的支持。如果 doGet 方法退出,标准 service 方法通过返回一个Allow header 来询问 OPTION。Allow header 指示对GET、HEAD、OPTION和TRACE的支持。
5. 你会自动获得对TRACE请求的支持。TRACE请求方法用于客户端的调试。它只返回HTTP请求header给客户端。


  核心提示:如果你的servlet处理GET和POST方式相同,那么让你的doPost方法调用doGet方法,或者反过来。不要直接覆盖service方法。

doGET、doPost及其它doXxx方法这些方法是你servlet的主体。你百分之九十的时间都只用去关心GET和POST请求,所以你需要覆盖doGet和doPost方法。如果你需要,你也可以为了处理DELETE请求而覆盖doDelete方法;为处理PUT请求而覆盖doPut;为处理OPTIONS请求覆盖doOptions;为处理TRACE请求覆盖doTrace。

SingleThreadModel接口:
  一般情况下,系统为每个servlet创建一个实例,为每个请求创建一个新的线程。当一个新的请求到来而另一个请求产生的线程还在执行中时,就会有多个线程并发执行。这就意味着你的doGet和doPost方法必须注意到共享数据和领域的同步访问问题,因为多个线程可能会同时尝试访问同一块数据。如果你想避免多线程的并发访问,你可以使你的servlet实现SingleThreadModel接口,如下所示:

public class YourServlet extends HttpServlet
  implements SingleThreadModel {
  ...
}

如果你实现了这个接口,系统将会确保servlet的一个实例同时只会被一个请求线程访问。这通过两种方法实现。其一,系统将请求放入队列中,在同一时间只传递一个给servlet的单个实例;其二,创建一个多实例池,每个实例同一时间只控制一个请求。这意味着你不必担心servlet的实例变量的并发访问。但是,你仍然需要同步化类变量(静态变量)和servlet之外的共享数据的访问。

如果你的servlet的访问率很高,那么通同步化访问你的整个servlet将会极大降低性能。所以在使用SingleThreadModel方法时一定要考虑再三。

destroy方法:

如果服务器管理员明确要求卸载一个servelt的实例,或者某servlet已经空闲了很长时间,服务器会移除先前装载的servlet实例。移除之前服务器会调用servlet的destroy方法。Servlet可以使用这个方法关闭数据库连接、中断后台线程、向磁盘写入cookie列表、保存点击数数据以及其他清理动作。你应该意识到Web服务器会有崩溃的危险。并不是所有服务器都是用象JAVA这样相对可靠的语言编写的。某些语言容易产生譬如数组越界、违法的类型转换、指针问题造成的内存泄露等等问题。但JAVA也不是万能的,比方说它不能阻止你快步奔向电脑时被电线拌倒。同样,不要把destroy当作唯一写数据回硬盘的方法。类似保存点击数或者写cookie列表这样的行为应该有计划地周期性地进行。 

分享到:
评论

相关推荐

    Servlet-Servlet生命周期

    ### Servlet生命周期详解 #### 一、引言 在Java Web开发中,Servlet作为一种重要的技术,被广泛应用于构建动态网页和处理客户端请求。了解Servlet的生命周期对于深入理解和掌握Servlet的工作机制至关重要。本文将...

    servlet生命周期详解

    初始化阶段是整个Servlet生命周期的第一个关键步骤,它标志着Servlet的开始。此阶段主要由以下步骤组成: 1. **Servlet容器加载Servlet类**:Servlet容器负责加载Servlet类,并将.Class文件的数据读入内存。这一...

    servlet生命周期演示代码

    ### Servlet 生命周期演示代码详解 #### 一、Servlet 生命周期概述 在深入分析代码之前,我们先来了解一下 Servlet 的生命周期。Servlet 的生命周期主要包括三个阶段:初始化 (`init` 方法)、请求处理 (`service` ...

    SERVLET生命周期与JSP生命周期比较

    ### SERVLET生命周期与JSP生命周期比较 #### 一、引言 在现代Web开发中,Servlet和JSP是两种非常重要的技术,它们都属于Java EE平台的一部分,主要用于构建动态Web应用程序。这两种技术各有特点,但又紧密相关,...

    Servlet 介绍 以及Servlet生命周期(详细)

    **Servlet生命周期** Servlet的生命周期可以分为三个主要阶段:初始化、服务和销毁。 1. **初始化阶段**: - 当Servlet首次被请求或者在web应用启动时,容器(如Tomcat)会加载Servlet类,并调用`init()`方法进行...

    Servlet生命周期

    ### Servlet 生命周期详解 #### 一、概述 Servlet 是 Java Web 开发的核心技术之一,用于处理客户端的 HTTP 请求并返回响应。了解 Servlet 的生命周期对于更好地控制和优化 Web 应用程序至关重要。Servlet 的生命...

    servlet生命周期

    #### 三、Servlet生命周期详解 ##### 实例化 - **按需创建**:默认情况下,当第一次HTTP请求到达时,容器会创建Servlet的实例。 - **预加载**:通过在`web.xml`中配置`<load-on-startup>`标签,可以在应用启动时...

    解读servlet生命周期

    Servlet生命周期是Java Web开发中一个关键的概念,它描述了Servlet从创建到销毁的整个过程,这个过程由Servlet容器(如Tomcat)进行管理。Servlet生命周期主要分为三个阶段:初始化阶段、运行阶段和销毁阶段。 1. ...

    servlet生命周期和模版设计模式

    Servlet生命周期和模板设计模式是Java Web开发中的两个关键概念,它们在构建动态Web应用程序时起着至关重要的作用。 首先,让我们深入理解Servlet的生命周期。Servlet是Java编程语言中的一种接口,用于扩展服务器的...

    Servlet 生命周期.pdf

    在Servlet生命周期中,init()方法只会被调用一次,service()方法会在每次用户请求时被调用,destroy()方法只会被调用一次,在Servlet生命周期结束时被调用。Servlet生命周期的正确实现是保证Servlet正确运行的关键。

    java servlet生命周期

    java servlet生命周期 java servlet生命周期

    servlet生命周期详细图解(矢量图)

    servlet生命周期详细图解,矢量图。 详细的解释请参考本人博客:http://blog.csdn.net/dwyers/article/details/38435949

    Servlet生命周期示意图

    关于对Servlet声明周期的图例示意!

    Servlet生命周期,http

    Servlet生命周期主要包括三个阶段:加载、初始化和销毁。当Web容器启动或者第一次接收到对Servlet的请求时,Servlet会被加载并实例化。然后,调用`init()`方法进行初始化,这个方法可以用来设置Servlet的初始状态...

    Java WEB 篇七 Servlet 生命周期.xmind

    Java WEB 篇七 Servlet 生命周期

Global site tag (gtag.js) - Google Analytics