转载:http://blog.csdn.net/javaloveiphone/article/details/8154791

内容:

一、先从servlet容器说起:大家最为熟悉的servlet容器就是Tomcat ,Servlet 容器是如何管理 Servlet?

先看一下tomcat的容器模型:

从上图可以看出 Tomcat 的容器分为四个等级,真正管理Servlet 的容器是Context 容器,一个 Context 对应一个 Web 工程

从上图可以看出 Tomcat 的容器分为四个等级,真正管理Servlet 的容器是Context 容器,一个 Context 对应一个 Web 工程

Tomcat 的容器等级中,Context 容器是直接管理 Servlet 在容器中的包装类Wrapper(StandardWrapper)的容器,所以 Context 容器如何运行将直接影响 Servlet 的工作方式。

这里解释一下servlet的包装类:StandardWrapper,这里有个疑问,为什么要将 Servlet 包装成 StandardWrapper 而不直接是 Servlet 对象。因为StandardWrapper 是 Tomcat 容器中的一部分,它具有容器的特征,而 Servlet 为一个独立的 web 开发标准,不应该强耦合在 Tomcat 中。

除了将 Servlet 包装成 StandardWrapper 并作为子容器添加到 Context 中,其它的所有 web.xml 属性都被解析到 Context 中,所以说 Context 容器才是真正运行 Servlet 的 Servlet 容器。一个 Web 应用对应一个 Context 容器,容器的配置属性由应用的 web.xml 指定,这样我们就能理解 web.xml 到底起到什么作用了

二、下面简述一下servlet的工作工程:

Web服务器在与客户端交互时.Servlet的工作过程是:

1.     在客户端对web服务器发出请求

2.     web服务器接收到请求后将其发送给Servlet

3.     Servlet容器为此产生一个实例对象并调用ServletAPI中相应的方法来对客户端HTTP请求进行处理,然后将处理的响应结果返回给WEB服务器.

4.     web服务器将从Servlet实例对象中收到的响应结构发送回客户端.

三、servlet的生命周期:

如上图所示,Servlet的生命周期可以分为四个阶段,即装载类及创建实例阶段、初始化阶段、服务阶段和实例销毁阶段。下面针对每个阶段的编程任务及注意事项进行详细的说明。

1、创建servlet实例:

在默认情况下Servlet实例是在第一个请求到来的时候创建,以后复用。如果有的Servlet需要复杂的操作需要载初始化时完成,比如打开文件、初始化网络连接等,可以通知服务器在启动的时候创建该Servlet的实例。具体配置如下:

<servlet>

      <servlet-name>TimeServlet</servlet-name>

      <servlet-class>com.allanlxf.servlet.basic.TimeServlet</servlet-class>

      <load-on-startup>1</load-on-startup>

    
</servlet>

创建servlet对象的相关类结构:

2、初始化

一旦Servlet实例被创建,Web服务器会自动调用init(ServletConfig config)方法来初始化该Servlet。其中方法参数config中包含了Servlet的配置信息,比如初始化参数,该对象由服务器创建。

I.如何配置Servlet的初始化参数?

在web.xml中该Servlet的定义标记中,比如:

<servlet>

         <servlet-name>TimeServlet</servlet-name>

         <servlet-class>com.allanlxf.servlet.basic.TimeServlet</servlet-class>

        <init-param>

            <param-name>user</param-name>

            <param-value>username</param-value>

       </init-param>

       <init-param>

           <param-name>blog</param-name>

           <param-value>http://。。。</param-value>

       </init-param>
    </servlet>

配置了两个初始化参数user和blog它们的值分别为usernamehttp://。。。, 这样以后要修改用户名和博客的地址不需要修改Servlet代码,只需修改配置文件即可。

II.如何读取Servlet的初始化参数?

ServletConfig中定义了如下的方法用来读取初始化参数的信息:

public String getInitParameter(String name)

参数:初始化参数的名称。

          返回:初始化参数的值,如果没有配置,返回null。

III.init(ServletConfig)方法执行次数

在Servlet的生命周期中,该方法执行一次。

IV.init(ServletConfig)方法与线程

     该方法执行在单线程的环境下,因此开发者不用考虑线程安全的问题。

V.init(ServletConfig)方法与异常

   该方法在执行过程中可以抛出ServletException来通知Web服务器Servlet实例初始化失败。一旦ServletException抛出,Web服务器不会将客户端请求交给该Servlet实例来处理,而是报告初始化失败异常信息给客户端,该Servlet实例将被从内存中销毁。如果在来新的请求,Web服务器会创建新的Servlet实例,并执行新实例的初始化操作

3、服务

   
一旦Servlet实例成功创建及初始化,该Servlet实例就可以被服务器用来服务于客户端的请求并生成响应。在服务阶段Web服务器会调用该实例的service(ServletRequest
request, ServletResponse
response)方法,request对象和response对象有服务器创建并传给Servlet实例。request对象封装了客户端发往服务器端的信息,response对象封装了服务器发往客户端的信息。

I. service()方法的职责

service()方法为Servlet的核心方法,客户端的业务逻辑应该在该方法内执行,典型的服务方法的开发流程为:

解析客户端请求-〉执行业务逻辑-〉输出响应页面到客户端

II.service()方法与线程

为了提高效率,Servlet规范要求一个Servlet实例必须能够同时服务于多个客户端请求,即service()方法运行在多线程的环境下,Servlet开发者必须保证该方法的线程安全性。

III.service()方法与异常

service()方法在执行的过程中可以抛出ServletException和IOException。其中ServletException可以在处理客户端请求的过程中抛出,比如请求的资源不可用、数据库不可用等。一旦该异常抛出,容器必须回收请求对象,并报告客户端该异常信息。IOException表示输入输出的错误,编程者不必关心该异常,直接由容器报告给客户端即可。

编程注意事项说明:

1) 当Server Thread线程执行Servlet实例的init()方法时,所有的Client Service
Thread线程都不能执行该实例的service()方法,更没有线程能够执行该实例的destroy()方法,因此Servlet的init()方法是工作在单线程的环境下,开发者不必考虑任何线程安全的问题。

2) 当服务器接收到来自客户端的多个请求时,服务器会在单独的Client Service
Thread线程中执行Servlet实例的service()方法服务于每个客户端。此时会有多个线程同时执行同一个Servlet实例的service()方法,因此必须考虑线程安全的问题。

3) 请大家注意,虽然service()方法运行在多线程的环境下,并不一定要同步该方法。而是要看这个方法在执行过程中访问的资源类型及对资源的访问方式。分析如下:

i.
如果service()方法没有访问Servlet的成员变量也没有访问全局的资源比如静态变量、文件、数据库连接等,而是只使用了当前线程自己的资源,比如非指向全局资源的临时变量、request和response对象等。该方法本身就是线程安全的,不必进行任何的同步控制。

ii. 如果service()方法访问了Servlet的成员变量,但是对该变量的操作是只读操作,该方法本身就是线程安全的,不必进行任何的同步控制。

iii. 如果service()方法访问了Servlet的成员变量,并且对该变量的操作既有读又有写,通常需要加上同步控制语句。

iv. 如果service()方法访问了全局的静态变量,如果同一时刻系统中也可能有其它线程访问该静态变量,如果既有读也有写的操作,通常需要加上同步控制语句。

v. 如果service()方法访问了全局的资源,比如文件、数据库连接等,通常需要加上同步控制语句。

4、销毁

当Web服务器认为Servlet实例没有存在的必要了,比如应用重新装载,或服务器关闭,以及Servlet很长时间都没有被访问过。服务器可以从内存中销毁(也叫卸载)该实例。Web服务器必须保证在卸载Servlet实例之前调用该实例的destroy()方法,以便回收Servlet申请的资源或进行其它的重要的处理。

Web服务器必须保证调用destroy()方法之前,让所有正在运行在该实例的service()方法中的线程退出或者等待这些线程一段时间。一旦destroy()方法已经执行,Web服务器将拒绝所有的新到来的对该Servlet实例的请求,destroy()方法退出,该Servlet实例即可以被垃圾回收。

四、servlet解析客户端http请求流程图:

1.     web客户向Servlet容器发出HTTP请求;

2.     Servlet容器解析web的HTTP请求.

3.     Servlet容器创建一个HttpRequest对象,在这个对象中封装了http请求信息;

4.     Servlet容器创建一个HttpResponse对象;

5.     Servlet容器(如果访问的该servlet不是在服务器启动时创建的,则先创建servlet实例并调用init()方法初始化对象)调用HttpServlet的service()方法,把HttpRequest和HttpResponse对象为service方法的参数传给HttpServlet对象;

6.     HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;

7.     HttpServlet调用HttpResponse的有关方法,生成响应数据;

8.    Servlet容器把HttpServlet的响应结果传给web客户.

如果转载的内容侵犯了您的隐私,请联系我删除。

《收藏》对servlet原理讲解特别详细的更多相关文章

  1. OAuth的机制原理讲解及开发流程

    本想前段时间就把自己通过QQ OAuth1.0.OAuth2.0协议进行验证而实现QQ登录的心得及Demo实例分享给大家,可一直很忙,今天抽点时间说下OAuth1.0协议原理,及讲解下QQ对于Oaut ...

  2. ElasticSearch之 控制相关度原理讲解

    控制相关度 相关度评分背后的理论 如何计算评分的 Lucene 使用布尔模型(Boolean model) 查找匹配文档 并主要的借鉴了 词频/逆向文档频率(term frequency/invers ...

  3. MongoDB优化,建立索引实例及索引机制原理讲解

    MongoDB优化,建立索引实例及索引机制原理讲解 为什么需要索引? 当你抱怨MongoDB集合查询效率低的时候,可能你就需要考虑使用索引了,为了方便后续介绍,先科普下MongoDB里的索引机制(同样 ...

  4. 【SpringBoot】单元测试进阶实战、自定义异常处理、t部署war项目到tomcat9和启动原理讲解

    ========================4.Springboot2.0单元测试进阶实战和自定义异常处理 ============================== 1.@SpringBoot ...

  5. HTML5裁剪图片并上传至服务器实现原理讲解

    HTML5裁剪图片并上传至服务器实现原理讲解   经常做项目需要本地上传图片裁剪并上传服务器,比如会议头像等功能,但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁 ...

  6. 红黑树之 原理和算法详细介绍(阿里面试-treemap使用了红黑树) 红黑树的时间复杂度是O(lgn) 高度<=2log(n+1)1、X节点左旋-将X右边的子节点变成 父节点 2、X节点右旋-将X左边的子节点变成父节点

    红黑树插入删除 具体参考:红黑树原理以及插入.删除算法 附图例说明   (阿里的高德一直追着问) 或者插入的情况参考:红黑树原理以及插入.删除算法 附图例说明 红黑树与AVL树 红黑树 的时间复杂度 ...

  7. (转)JVM原理讲解和调优

    背景:jvm实际调优在面试时候经常被问到,所以有必要认真总结一番. 转自:JVM原理讲解和调优 四.JVM内存调优 首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存 ...

  8. Docker Compose 部署 Redis 及原理讲解 | 懒人屋

    原文:Docker Compose 部署 Redis 及原理讲解 | 懒人屋 Docker Compose 部署 Redis 及原理讲解  4.4k  字    16  分钟    2019-10-1 ...

  9. 阿里云专有网络配置以及交换机配置+ip、子网掩码、ip网段计算原理讲解

    在阿里云上购买ECS或者其他服务,如redis.polardb时,需要配置专有网络,阿里的文档写的总体上还是比较抽象的,没有一定的网络基础,会一脸懵. 所以这里我来进行专有网络和交换机的配置,以及ip ...

随机推荐

  1. Beyond Globally Optimal: Focused Learning

    这里对WWW 2017文章<Beyond Globally Optimal: Focused Learning for Improved Recommendations>进行一个简单的分析 ...

  2. zookeeper伪分布式集群环境搭建

    step1.下载 下载地址:http://zookeeper.apache.org/releases.html 将下载的压缩包放到用户家目录下(其他目录也可以) step2.解压 $tar –zxvf ...

  3. Grails框架使用指南

    Grails框架使用指南,详解Grails框架!cnxieyang@163.com

  4. Elastic FileBeat 快速入门

    背景 用过ELK(Elasticsearch, Logstash, Kibana)的人应该都面临过同样的问题,Logstash虽然功能强大:支持许多的input/output plugin.强大的fi ...

  5. Codechef:Path Triples On Tree

    Path Triples On Tree 题意是求树上都不相交或者都相交的路径三元组数量. 发现blog里没什么树形dp题,也没有cc题,所以来丢一道cc上的树形dp题. 比较暴力,比较恶心 #inc ...

  6. Flexbox 练习和总结

    练习地址: http://flexboxfroggy.com/ Welcome to Flexbox Froggy, a game where you help Froggy and friends ...

  7. zookeeper的安装以及启动jps进程

    2.7.1安装 将下载好的安装包,解压到指定位置,这里为直接解压到当前位置,命令如下: tar -zxvf zk-{version}.tar.gz 修改zk配置,将zk安装目录下conf/zoo_sa ...

  8. [国嵌攻略][149][Yaffs2文件系统应用]

    嵌入式系统自启动 MTD技术通过把Nand FLash划分成bootloader分区,Linux kernel分区和file system分区来达到自启动的效果. 配置和编译内核 1.配置Linux内 ...

  9. 如何动态修改网页的标题(title)?

    有时候我们需要复用一个页面,但是又希望他们拥有各自的标题,这时候就需要动态的去更改页面的title了,不然所有页面都是一个标题. 这时候就会想到使用js或jQuery去实现了. 1.js方式. 首先, ...

  10. 平安E行销扫脸打卡/人寿国寿e店云参会钉钉考勤,原来这么轻易被破解!

    由于近几年人们的保险意识越来越强,身边有很多朋友都在中国人寿,中国平安等保险公司上班薪水高,工作自由,又可以学习很多保险理财的知识,每天早会个2~3个小时,剩下的基本都是自己的时间,(vx:99508 ...