一、Servlet 和 Servlet容器

1.1 Servlet介绍

1.1.1 servlet是什么

Servlet 是 Server Applet 的缩写,译为“服务器端小程序”,是一种使用 Java 语言来开发动态网站的技术。Servlet 虽然被称作“小程序”,但是它的功能却异常强大,因为它是基于 Java 的,几乎可以使用所有的 Java API,Java 能做的事情,Servlet 也能做。

1.1.2 为什么会出现servlet

Java 是一种功能强大的通用型编程语言,可以处理 HTTP 请求,可以访问数据库,可以生成 HTML 代码,您完全可以使用原生 Java 来开发动态网站。但是,使用原生 Java 开发动态网站非常麻烦,需要自己解析 HTTP 请求的报头,需要自己分析用户的请求参数,需要自己加载数据库组件……种种原因导致使用原生 Java 开发动态网站几乎是一件不能被接受的事情。正是基于这种原因,Java 官方后来推出了 Servlet 技术,它对开发动态网站需要使用的原生 Java API 进行了封装,形成了一套新的 API,称为 Servlet API。

使用 Servlet 开发动态网站非常方便,程序员只需要集中精力处理业务逻辑,不需要再为那些基础性的、通用性的功能编写代码,这使得 Servlet 在动态网站开发领域具备了很高的实用性。

Servlet 基于 Java,可以使用几乎全部的 Java API,所以它的功能异常强大,完全可以胜任企业级开发,能够处理那些高并发、大吞吐量、业务逻辑复杂的应用场景。

您可以这样理解,Servlet 是 Sun 公司推出的一种基于 Java 的动态网站开发技术。编写 Servlet 代码需要遵循 Java 语法,一个 Servlet 程序其实就是一个按照 Servlet 规范编写的 Java 类。Servlet 程序需要先编译成字节码文件(.class文件),然后再部署到服务器运行。

Servlet 是第一代 Java Web 开发技术,用它开发非常麻烦,所以 Java 官方又推出了第二代 Web 开发技术JSP,JSP 才是现代化的 Web 开发技术,这里不多说(以上内容参考ref1)。

简而言之,servlet可以理解服务器端处理数据的java小程序

1.1.3 servlet的管理

我们编写的 Servlet 类没有 main() 函数,不能独立运行,那我们如何启动一个servlet,如何结束一个servlet,如何寻找一个servlet? 这一切都受控于另一个java应用,这个应用我们就称之为Servlet容器。servlet容器帮助我们管理着servlet等,使我们只需要将重心专注于业务逻辑。

1.2 Servlet容器(Web容器)

在介绍Servlet容器之前,我们需要介绍下相关历史。

1.2.1 传统的Web服务器只能支持静态资源的访问

Web 服务器是一种对外提供 Web 服务的软件,它可以接收浏览器的 HTTP 请求,并将处理结果返回给浏览器。部署网站一般需要 Web 服务器的支持,例如:
运行 PHP 网站一般选择 Apache 或者 Nginx;
运行 ASP/ASP.NET 网站一般选择 IIS;
运行 Python 网站一般选择内置的 WSGI 服务器模块——wsgiref。

我们通常所说的 Web 服务器,比如 Apache、Nginx、IIS 等,它们的功能往往都比较单一,只能提供 http(s) 服务,让用户访问静态资源(HTML 文档、图片、CSS 文件、JavaScript 文件等),它们不能执行任何编程语言,也不能访问数据库,更不能让用户注册和登录。也就是说,如果只有 Web 服务器,那您只能部署静态网站,不能部署动态网站。
在这里插入图片描述

1.2.2 动态网站部署的需求来了

而随着互联网的发展,交互越发得重要,单纯的静态文件满足不了需求。业务变得复杂,需要我们编写代码来处理诸多业务。需要根据 HTTP 请求调用不同的业务逻辑来响应,那就需要部署动态网站。

要想部署动态网站,必须要有编程语言运行环境(运行时,Runtime)的和数据库管理系统的支持。即部署动态网站一般至少需要三个组件,分别是 Web 服务器、运行时和数据库。例如,部署 PHP 网站一般选择「Apache + PHP 运行时 + MySQL」的组合:
在这里插入图片描述
运行环境(运行时):

开发网站使用的编程语言一般都是脚本语言(比如 PHP、ASP、Python),部署网站时都是将源代码直接扔到服务器上,然而源代码自己并不能运行,必须要有解释器的支持;当用户访问动态页面时,解释器负责分析、编译和执行源代码,然后得到处理结果。解释器是执行脚本语言的核心部件,除此以外还有一些辅助性的部件,例如:

  • 垃圾回收器:负责及时释放不需要的内存,腾出资源供其它页面使用;
  • 标准库:任何编程语言都会附带标准库,它们提供了很多通用性的功能,极大地提高了开发效率,避免重复造轮子。

我们习惯将以上各种支持脚本语言运行的部件统称为运行环境,或者运行时(Runtime)。

数据库:
Web 服务器不带数据库,编程语言也不带数据库,数据库是一款独立的软件;要想实现用户注册、发布文章、提交评论等功能,就必须安装一款数据库,比如 MySQL、Oracle、SQL Server 等。

1.2.3 Servlet 容器

Servlet 是基于 Java 语言的,运行 Servlet 必然少不了 JRE 的支持,它负责解析和执行字节码文件(.class文件)。然而 JRE 只包含了 Java 虚拟机(JVM)、Java 核心类库和一些辅助性性文件,它并不支持 Servlet 规范。要想运行 Servlet 代码,还需要一种额外的部件,该部件必须支持 Servlet 规范,实现了 Servlet 接口和一些基础类,这种部件就是 Servlet 容器

Servlet 容器就是 Servlet 代码的运行环境(运行时),它除了实现 Servlet 规范定义的各种接口和类,为 Servlet 的运行提供底层支持,还需要管理由用户编写的 Servlet 类,比如实例化类(创建对象)、调用方法、销毁类等。
在这里插入图片描述
一个动态页面对应一个 Servlet 类,开发一个动态页面就是编写一个 Servlet 类,当用户请求到达时,Servlet 容器会根据配置文件(web.xml)来决定调用哪个类。

Web 服务器是整个动态网站的“大门”,用户的 HTTP 请求首先到达 Web 服务器,Web 服务器判断该请求是静态资源还是动态资源:如果是静态资源就直接返回,此时相当于用户下载了一个服务器上的文件;如果是动态资源将无法处理,必须将该请求转发给 Servlet 容器。

Servlet 容器接收到请求以后,会根据配置文件(web.xml)找到对应的 Servlet 类,将它加载并实例化,然后调用其中的方法来处理用户请求;处理结束后,Servlet 容器将处理结果再转交给 Web 服务器,由 Web 服务器将处理结果进行封装,以 HTTP 响应的形式发送给最终的用户。

1.2.4 web 容器

常用的 Web 容器有 Tomcat、Jboss、Jetty、WebLogic 等,其中 Tomcat 由 Java 官方提供,是初学者最常使用的。

为了简化部署流程,Web 容器往往也会自带 Web 服务器模块,提供基本的 HTTP 服务,因此这里的 Web容器 = Web服务器 + Servlet容器,所以您可以不用再安装 Apache、IIS、Nginx 等传统意义上的服务器,只需要安装一款 Web 容器,就能部署 Servlet 网站了。

正是由于这个原因,有的教材将 Tomcat 称为 Web 容器,有的教材又将 Tomcat 称为 Web 服务器;日常讨论时,也会将web容器称为servlet容器,两者的概念已经非常模糊了。

将 Web容器当做服务器使用后,上面的流程图就变成了下面的样子:
在这里插入图片描述
注意,Servlet 容器自带的 Web 服务器模块虽然没有传统的 Web 服务器强大,但是也足以应付大部分开发场景。

总结下来,Servlet 容器就是 Servlet 程序的运行环境,它主要包含以下几个功能:

  • 实现 Servlet 规范定义的各种接口和类,为 Servlet 的运行提供底层支持;
  • 管理用户编写的 Servlet 类,以及实例化以后的对象;
  • 提供 HTTP 服务,相当于一个简化的服务器。

二、Servlet容器的作用

servlet需要由servlet容器来管理,那么采取这种机制有什么好处呢?

2.1 通信支持

利用容器提供的方法,你可以简单的实现servlet与web服务器的对话。否则你就要自己建立socket,监听端口,创建新的流等等一系列复杂的操作。而容器的存在就帮我们封装这一系列复杂的操作。使我们能够专注于servlet中的业务逻辑的实现。

web服务器监听来自特定端口(通常是80端口)的HTTP请求,当客户端(使用web浏览器的用户)发送一个HTTP请求时,Servlet容器会创建新的HttpServletRequest和HttpServletResponse对象,并且把它们传递给与请求URL匹配的Servlet实例的方法进行处理(所有的这些都使用同一个线程)。

request对象提供了获取HTTP请求的所有信息的入口,比如请求头和请求实体。response对象提供了控制和发送HTTP响应的便利方法,比如设置响应头和响应实体(通常是JSP生成的HTML内容)。当HTTP响应被提交并结束后,request和response对象都会被销毁。

2.2 生命周期管理

容器负责servlet的整个生命周期。如何加载类,实例化和初始化servlet,调用servlet方法,并使servlet实例能够被垃圾回收。有了容器,我们就不用花精力去考虑这些资源管理垃圾回收之类的事情。

当Servlet容器启动时,它会部署并加载所有的web应用。当web应用被加载时,Servlet容器会一次性为每个应用创建Servlet上下文(ServletContext)并把它保存在内存里。Servlet容器会处理web应用的web.xml文件,并且一次性创建在web.xml里定义的Servlet、Filter和Listener,同样也会把它们保存在内存里。

当Servlet容器关闭时,它会卸载所有的web应用和ServletContext,所有的Servlet、Filter和Listner实例都会被销毁。

2.3 多线程支持

容器会自动为接收的每个servlet请求创建一个新的java线程,servlet运行完之后,容器会自动结束这个线程。

2.4 声明式实现安全

利用容器,可以使用xml部署描述文件来配置安全性,而不必将其硬编码到servlet中。

2.5 jsp支持

容器将jsp翻译成java!

三、容器如何处理请求

3.1 容器处理请求的过程

step1: client点击一个URL,其URL指向一个servlet而不是静态界面
在这里插入图片描述
step2: 容器识别出这个请求索要的是一个servlet,所以创建两个对象:

  • httpservletrequest
  • httpservletresponse
    在这里插入图片描述
    step3: 容器根据请求中的URL找到对应的servlet,为这个请求创建或分配一个线程,并把两个对象request和response传递到servlet线程中
    在这里插入图片描述
    step4: 容器调用servlet的service()方法。根据请求的不同类型,service()方法会调用doGet()或者doPost()方法
    在这里插入图片描述
    step5: doGet()方法生成动态页面,然后把这个页面填入到response对象中,此时,容器仍然拥有response对象的引用。
    在这里插入图片描述
    step6: 线程结束。容器把response对象转换成http响应,传回client,并销毁response和request对象。
    在这里插入图片描述

3.2 URL与servlet映射模式

<servlet>
    <servlet-name>Ch1Servlet</servlet-name>
    <servlet-class>ch1Servlet.Ch1Servlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Ch1Servlet</servlet-name>
    <url-pattern>/Ch1Servlet</url-pattern>
  </servlet-mapping>

servlet有三个名字:

  • 客户知道的URL名:
    <url-pattern>/Ch1Servlet</url-pattern>
  • 部署人员知道的秘密的内部名:
    <servlet-name>Ch1Servlet</servlet-name>
  • 实际文件名
    <servlet-class>ch1Servlet.Ch1Servlet</servlet-class>

四、参考文档

ref1. Servlet到底是什么
ref2. Servlet容器(Web容器)是什么
ref3. 为什么要有 Servlet ,什么是 Servlet 容器,什么是 Web 容器?
ref4. web开发中 web 容器的作用(如tomcat)
ref5. Web容器的作用

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐