servlet学习笔记(1)——Servlet API

时间:2022-02-05 21:05:30

Servlet简介

Servlet是JavaWeb应用中最核心的组件。Servlet运行在Servlet容器中,能够为各种各样的客户请求提供相应服务。Servlet可以轻而易举地完成以下任务:
- 动态生成HTML文档。
- 把请求转发给同一个Web应用中的其他Servlet组件。
- 把请求转发给其他Web应用中的其他Servlet组件。
- 读取客户端的Cookie,以及向客户端写入Cookie。
- 访问其他服务器资源(如数据库或基于Java的应用程序)。


Servlet生命周期、工作原理

  1. Servlet 生命周期:Servlet 加载—>实例化—>服务—>销毁。
  2. init():在Servlet的生命周期中,仅执行一次init()方法。它是在服务器装入Servlet时执行的,负责初始化Servlet对象。可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init()。
  3. service():它是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。
  4. destroy(): 仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当Servlet对象退出生命周期时,负责释放占用的资源。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。

Tomcat 与 Servlet 是如何工作的:

servlet学习笔记(1)——Servlet API

步骤:

  1. Web Client 向Servlet容器(Tomcat)发出Http请求
  2. Servlet容器接收Web Client的请求
  3. Servlet容器创建一个HttpRequest对象,将WebClient请求的信息封装到这个对象中。
  4. Servlet容器创建一个HttpResponse对象
  5. Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给 HttpServlet 对象。
  6. HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息。
  7. HttpServlet调用HttpResponse对象的有关方法,生成响应数据。
  8. Servlet容器把HttpServlet的响应结果传给Web Client。

Servlet工作原理:

  1. 首先简单解释一下Servlet接收和响应客户请求的过程,首先客户发送一个请求,Servlet是调用service()方法对请求进行响应的,通过源代码可见,service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没有doGet()、doPost()等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。
  2. 每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是上文提到的init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。
  3. Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest、ServletResponse 强转为HttpRequest 和 HttpResponse。

创建Servlet对象的时机:

  1. Servlet容器启动时:读取web.xml配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,同时将ServletConfig对象作为参数来调用Servlet对象的init方法。
  2. 在Servlet容器启动后:客户首次向Servlet发出请求,Servlet容器会判断内存中是否存在指定的Servlet对象,如果没有则创建它,然后根据客户的请求创建HttpRequest、HttpResponse对象,从而调用Servlet 对象的service方法。
  3. Servlet Servlet容器在启动时自动创建Servlet,这是由在web.xml文件中为Servlet设置的属性决定的。从中我们也能看到同一个类型的Servlet对象在Servlet容器中以单例的形式存在。

Servlet最常用的对象

  • 请求对象(ServletRequest和HttpServletRequest):Servlet从该对象中获取来自客户端的请求信息。
  • 响应对象(ServletResponse和HttpServletResponse):Servlet通过该对象来生成响应结果。
  • Servlet配置对象(ServletConfig):当容器初始化一个Servlet对象时,会向Servlet提供一个ServletConfig对象,Servlet通过该对象来初始化参数信息及ServletContent对象。
  • Servlet上下文对象(ServletContent):Servlet通过该对象来访问容器为当前web应用提供的各种资源。

Servlet对象模型的静态结构

Servlet API主要由两个Java包组成

  • ==javax.servlet==:定义了Servlet接口及相关的通用接口和类。
  • ==javax.servlet.http==:主要定义了与HTTP协议相关的HttpServlet类、HttpServletRequest接口、HTTPServletResponse接口。

Servlet API的类框图
servlet学习笔记(1)——Servlet API

Servlet接口

javax.servlet.Servlet接口是Servlet API的核心接口,所有的Servlet类都必须实现这一接口。
Servlet接口定义的5个方法

方法名 作用 调用
init(ServletConfig config) 负责初始化Servlet对象。容器在创建好Servlet对象后,就会调用该方法。 由Servlet容器调用
service(ServletRequest req, ServletResponse res) 负责响应客户的请求,为客户提供响应的服务。当容器接收到客户端要求访问特定的Servlet对象的请求时,就会调用该Servlet对象的service方法 由Servlet容器调用
destroy() 负责释放Servlet对象占用的资源。当Servlet对象结束生命周期时,容器会调用此方法。 由Servlet容器调用
getServletConfig() 返回一个ServletConfig对象,在该对象中包含了Servlet的初始化参数信息 JavaWeb应用程序访问
getServletInfo() 返回一个字符串,该字符串中包含了Servlet的创建者、版本和版权等信息 JavaWeb应用程序调用

Servlet接口及其实现类框图

servlet学习笔记(1)——Servlet API

==GenericServlet抽象类==实现了Servlet接口和ServletConfig接口,但其主要身份是Servlet,此外,它还运用装饰模式,为自己附加了ServletConfig的装饰身份。在具体实现中,GenericServlet类包装了一个ServletConfig接口的实例,通过该实例来实现ServletConfig接口中的方法。

==HttpServlet抽象类==是GenericServlet的子类。HttpServlet类为Servlet接口提供了与HTTP协议相关的通用实现,也就是说,HttpServlet对象适合运行在与客户端采用HTTP协议通信的Servlet容器或者Web服务器中。在开发JavaWeb应用时,自定义的Servlet类一般都扩展HttpServlet类。

ServletRequest接口

在service(ServletRequest req, ServletResponse res)方法中有一个ServletRequest类型的参数。ServletRequest类表示来自客户端的请求。当Servlet容器接收到客户端要求访问特定Servlet请求时,容器先解析客户端的原始请求数据,把它包装成一个ServletRequest对象。当容器调用Servlet对象的service方法时,就可以吧ServletRequest对象作为参数传给service()方法。ServletRequest接口提供了一系列用于读取客户端请求数据的方法。如下:

方法 描述
getContentLength() 返回请求正文的长度。如果请求正文的长度未知,则返回-1。
getContentType() 获得请求正文的MIME类型。如果请求正文的类型未知,则返回null。
getInputStream() 返回用于读取请求正文的输入流。
getLocalAddr() 返回服务器端的ip地址。
getLocalName() 返回服务器端的主机名。
getLocalPort() 返回服务器端的FTP端口号。
getParameter(String name) 根据给定的请求参数名,返回来自客户请求中的匹配的请求参数值。
getProtocol() 返回客户端与服务器端通信所用的协议名称及版本号。
getReader() 返回用于读取字符串形式的请求正文的BufferedReader对象。
getRemoteAddr() 返回客户端的ip地址。
getRemoteHost() 返回客户端的主机名。
getRemotePort() 返回客户端的FTP端口号。
setAttribute(String name, Object object) 在请求范围内保存一个属性,参数name表示属性名,参数object表示属性值。
getAttribute(String name) 根据name参数给定的属性名,返回请求范围内的匹配的属性值。
removeAttribute(String name) 从请求范围内删除一个属性。

HttpServletRequest接口

是ServletRequest接口的子接口。HttpServletRequest接口提供了用于读取HTTP请求中相关信息的方法如下:

方法 描述
getContentPath() 返回客户端所请求访问的Web应用的url入口。
getCookies() 返回Http请求中的所有Cookie。
getHeader(String name) 返回HTTP请求头部的特定项。
getHeaderNames() 返回一个Enumeration对象,它包含了HTTP请求头部的所有项目名。
getMethod() 返回HTTP请求方式。
getRequestURI() 返回HTTP请求的头部的第一行中的URI。
getQueryString() 返回HTTP请求中的查询字符串,即URI中的“?”后面的内容。

ServletResponse接口

Servlet通过ServletResponse对象来生成响应结果。当Servlet容器接收到客户端要求访问的特定Servlet的请求时,容器会创建一个ServletResponse对象,并把它作为参数穿给Servlet的service方法。在Servlet接口中定义了一系列与生成响应结果相关的方法。如下:

方法 描述
setCharacterEncoding(String charset) 设置响应正文的字符编码。响应正文的默认字符编码为ISO-8859-1。
setContentLength(int len) 设置响应正文的长度。
setContentType(String type) 设置响应正文的MIME类型。
getCharacterEncoding() 返回响应正文的字符编码。
getContentType() 返回响应正文的MIME类型。
setBufferSize(int size) 设置用于存放响应正文数据的缓冲区大小。
getBuffereSize() 获得用于存放响应正文数据的缓冲区大小。
reset() 清空缓冲区内的正文数据,并且清空响应状态代码及响应头。
resetBuffer() 仅仅清空缓冲区内的正文数据,不清空响应状态代码及响应头。
flushBuffer() 强制性地把缓冲区内的响应正文数据发送到客户端。
isCommitted() 返回一个boolean类型的值。如果为true。表示缓冲区内的数据已经提交给客户,即数据已经发送到客户端。
getOutputStream() 返回一个ServletOutputStream对象,Servlet用它来输出二进制的正文数据。
getWriter() 返回一个printWriter对象,Servlet用它来输出字符串形式的正文数据。

为了提高输出数据的效率,ServletOutputStream和printWriter先把数据写到缓冲区内。当缓冲区的数据被提交给客户端后,ServletResponse的isCommitted()方法返回true,在一下几种情况下,缓冲区内的数据会被提交给客户,即数据被发送到客户端:
- 当缓冲区内的数据已满时,ServletOutputStream或者printWriter会自动把缓冲区内的数据自动发送给客户端,并且清空缓冲区。
- Servlet调用ServletResponse对象的flushBuffer()方法。
- Servlet调用ServletOutputStream或者printWriter对象的flush()方法或close()方法。

==为了确保ServletOutputStream或printWriter输出所有的数据都会被提交给客户,比较安全的做法是在所有数据都输出完毕后,调用ServletOutputStream或printWriter的close()方法。==

HttpServletResponse接口

是ServletResponse接口的子接口。HttpServletResponse接口提供了与HTTP协议相关的一些方法,Servlet可以通过这些方法来设置HTTP响应头或向客户端写Cookie。

方法 描述
addHeader(String name, String value) 向HTTP响应头中加入一项内容。
sendError(int sc) 向客户端发送一个代表特定错误的HTTP响应状态代码。
sendError(int sc, String msg) 向客户端发送一个代表特定错误的HTTP响应状态代码,并且发送具体的错误消息。
setHeader(String name, String value) 设置HTTP响应头中的一项内容。如果在响应头中已经存在这项内容,那么原先所做的设置将被覆盖。
setStatus(int sc) 设置HTTP响应的状态代码。
addCookie() 向HTTP响应中加入一个Cookie。

ServletConfig接口

当Servlet容器初始化一个Servlet对象时,会为这个Servlet对象创建一个ServletConfig对象。在ServletConfig对象中包含了Servlet对象的初始化参数信息,此外ServletConfig对象还与当前Web应用的ServletContext对象关联。Servlet容器在调用Servlet对象的init(ServletConfig config)方法时,会把ServletConfig对象作为参数传递给Servlet对象,init(ServletConfig config)方法会使得当前Servlet对象与ServletConfig对象之间建立关联关系。ServletConfig接口中定义了以下方法:

方法 描述
getInitParameter(String name) 根据给定的初始化参数名,返回匹配的初始化参数值。
getInitParameterNames() 返回一个Enumeration对象,里面包含了所有的初始化参数名。
getservletContext() 返回一个ServletContext对象。
getServletNames() 返回Servlet的名字。

ServletContext接口

ServletContext是Servlet与Servlet容器之间直接通信的接口。Servlet容器在启动一个Web应用时,会为它创建一个ServletContext对象。==每个Web应用都有唯一的ServletContext对象,可以把ServletContext对象形象地理解为Web应用的总管家,同一个Web应用中的所有Servlet对象都共享一个总管家,Servlet对象们可以通过这个总管家来访问容器中的各种资源。== ServletContext接口提供的方法可以分为以下几种类型:
1. 用于在Web应用范围内存取共享数据的方法。

方法 描述
setAttribute(String name, Object object) 把一个Java对象与一个属性名绑定,并把它存入到ServletContext中。参数name指定属性名,参数object表示共享数据。
getAttribute(String name) 根据参数给定的属性名,返回一个Object类型的对象,它表示ServletContext中与属性名匹配的属性值。
getAttributeNames 返回一个Enumeration对象,该对象包含了所有存放在ServletContext中的属性名。
removeAttribute(String name) 根据参数指定的属性名,从ServletContext中移除匹配的属性。

2. 访问当前Web应用的资源。

方法 描述
getContextPath() 返回当前Web应用的URL入口。
getInitParameter(String name) 根据给定的参数名,返回Web应用范围内匹配的初始化参数值。在web.xml文件中,直接在根元素下定义的元素表示应用范围内的初始化参数。
getInitParameterNames() 返回一个Enumeration对象,它包含了web应用范围内的所有初始化参数名。
getServletContextName() 返回web应用的名字,即web.xml文件中元素的值。
getRequestDispatcher(String path) 返回一个用于向其他web组件转发请求的RequestDispatcher对象。

3. 访问Servlet容器中的其他Web应用。

方法 描述
getContext(String uripath) 根据给定的参数指定的URI,返回当前Servlet容器中的其他Web应用的ServletContext对象

4. 访问Servlet容器的相关信息。

方法 描述
getMajorVersion() 返回Servlet容器支持的Java Servlet API的主版本号。
getMinorVersion() 返回Servlet容器支持的Java Servlet API的次版本号。
getServerInfo() 返回Servlet容器的名字和版本。

5. 访问服务器的文件系统资源。

方法 描述
getRealPath(String path) 根据参数指定的虚拟路径,返回文件系统中的一个真实路径。
getResource(String path) 返回一个映射到参数指定路径的URL
getResourceAsStream(String path) 返回一个用于读取参数指定的文件的输入流。
getMimeType() 返回参数指定的文件的MIME类型。

6. 输出日志。

方法 描述
log(String msg) 向Servlet的日志文件中写日志。
log(String message,Throwable throwable) 向Servlet日志文件中写错误日志,以及异常的堆栈信息。

学习教材:Tomcat与JavaWeb开发技术详解(第2版).孙卫琴著