热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

(转)Servlet的生命周期——初始化、运行、销毁全部过程

背景:面试中很基础的一个问题,所以有必要好好整理一番。Servlet体系结构是建立在Java多线程机制上的,它的生命周期由Web容器负责。当客户端第一次请求某个Se

背景:面试中很基础的一个问题,所以有必要好好整理一番。

 

Servlet体系结构是建立在 Java 多线程机制上的,它的生命周期由 Web 容器负责。

当客户端第一次请求某个 Servlet 时,Servlet 容器将会根据 web.xml 的配置文件实例化这个 Servlet 类。当有新的客户端请求该 Servlet 时,一般不会再实例化该 Servlet 类。

当有多个请求时,Servlet 容器会起多个线程来访问同一个 Servlet 实例的 service() 方法,如果该 Servlet 实例中有共享的实例变量,需要注意多线程安全问题。

生命周期

Servlet 生命周期定义了 Servlet 从创建到毁灭的整个过程,总共分为四个步骤。

调用 init() 方法初始化
调用 service() 方法来处理客户端的请求
调用 destroy() 方法释放资源,标记自身为可回收
被垃圾回收器回收

init() 方法

init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,用于 Servlet的初始化,初始化的数据,可以在整个生命周期中使用。


在下列时刻Servlet容器装载Servlet,共三种情况:

    1,Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的之间添加如下代码:

<loadon-startup>1loadon-startup> 

说明:
在servlet的配置当中,5的含义是:
标记容器是否在启动的时候就加载这个servlet。
当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载
正数的值越小,启动该servlet的优先级越高。 

    2,在Servlet容器启动后,客户首次向Servlet发送请求

    3,Servlet类文件被更新后,重新装载Servlet

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

 

初始化阶段步骤:
Ø Servlet容器加载servlet类,把它的. Class文件中的数据读到内存中。
Ø Servlet容器创建servletConfig对象。servletConfig对象包含了servlet的初始化配置信息。此外servlet容器还会使得servletConfig对象与当前的web应用的servletContext对象关联。
Ø Servlet容器创建servlet对象。
Ø Servlet容器调用servlet对象的init(ServletConfig config)方法。
通过初始化步骤,创建了servlet对象和servletConfig对象,并且servlet对象与servletConfig对象关联,而servletConfig对象又与当前对象的servletContext对象关联。当servlet容器完成servlet后,servlet对象只要通过getServletContext()方法就能得到web应用的servletContext对象。

 

service() 方法

service() 方法是执行实际任务的主要方法。 Servlet 容器(Tomcat、Jetty等)调用 service() 方法来处理来自客户端(浏览器)的请求,并把相应结果返回给客户端。

每次 Servlet 容器接收到一个 Http 请求, Servlet 容器会产生一个新的线程并调用 Servlet实例的 service 方法。 service 方法会检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut、doDelete 方法。所以,在编码请求处理逻辑的时候,我们只需要关注 doGet()、或doPost()的具体实现即可。

 

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

private Hashtable paramHashStringArray = new Hashtable();

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

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

destroy() 方法

destroy() 方法也只会被调用一次,在 Servlet 生命周期结束时调用。destroy() 方法主要用来清扫“战场”,执行如关闭数据库连接、释放资源等行为。

调用 destroy 方法之后,servlet 对象被标记为垃圾回收,等待 JVM 的垃圾回收器进行处理。

 

引申

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应用

 

Servlet与JSP的比较:

  有许多相似之处,都可以生成动态网页。

  JSP的优点是擅长于网页制作,生成动态页面比较直观,缺点是不容易跟踪与排错。

  Servlet是纯Java语言,擅长于处理流程和业务逻辑,缺点是生成动态网页不直观。

 

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。

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方法都是返回错误信息,

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);
    }
}

 

 

 

推荐阅读
  • springMVC JRS303验证 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • ssm框架整合及工程分层1.先创建一个新的project1.1配置pom.xml ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 本文探讨了如何在Classic ASP中实现与PHP的hash_hmac('SHA256', $message, pack('H*', $secret))函数等效的哈希生成方法。通过分析不同实现方式及其产生的差异,提供了一种使用Microsoft .NET Framework的解决方案。 ... [详细]
  • 访问一个网页的全过程
    准备:DHCPUDPIP和以太网启动主机,用一根以太网电缆连接到学校的以太网交换机,交换机又与学校的路由器相连.学校的这台路由器与一个ISP链接,此ISP(Intern ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
  • ListView简单使用
    先上效果:主要实现了Listview的绑定和点击事件。项目资源结构如下:先创建一个动物类,用来装载数据:Animal类如下:packagecom.example.simplelis ... [详细]
  • 搭建Jenkins、Ant与TestNG集成环境
    本文详细介绍了如何在Ubuntu 16.04系统上配置Jenkins、Ant和TestNG的集成开发环境,涵盖从安装到配置的具体步骤,并提供了创建Windows Slave节点及项目构建的指南。 ... [详细]
  • 利用Selenium与ChromeDriver实现豆瓣网页全屏截图
    本文介绍了一种使用Selenium和ChromeDriver结合Python代码,轻松实现对豆瓣网站进行完整页面截图的方法。该方法不仅简单易行,而且解决了新版Selenium不再支持PhantomJS的问题。 ... [详细]
  • Java项目分层架构设计与实践
    本文探讨了Java项目中应用分层的最佳实践,不仅介绍了常见的三层架构(Controller、Service、DAO),还深入分析了各层的职责划分及优化建议。通过合理的分层设计,可以提高代码的可维护性、扩展性和团队协作效率。 ... [详细]
  • 在 Android 开发中,通过 Intent 启动 Activity 或 Service 时,可以使用 putExtra 方法传递数据。接收方可以通过 getIntent().getExtras() 获取这些数据。本文将介绍如何使用 RoboGuice 框架简化这一过程,特别是 @InjectExtra 注解的使用。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 本文详细介绍了Java中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • 本文详细介绍如何使用 Python 集成微信支付的三种主要方式:Native 支付、APP 支付和 JSAPI 支付。每种方式适用于不同的应用场景,如 PC 网站、移动端应用和公众号内支付等。 ... [详细]
author-avatar
桃子小1992
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有