JavaWeb 之 Servlet 指南
# JavaWeb 之 Servlet 指南
# JavaWeb 简介
# Web 应用程序
Web,在英语中 web 即表示网页的意思,它用于表示 Internet 主机上供外界访问的资源。
Web 应用程序是一种可以通过 Web 访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件。
Internet 上供外界访问的 Web 资源分为:
- 静态 web 资源:指 web 页面中供人们浏览的数据始终是不变。常见静态资源文件:html、css、各种图片类型(jpg、png)
- 动态 web 资源:指 web 页面中供人们浏览的数据是由程序产生的,不同时间点访问 web 页面看到的内容各不相同。常见动态资源技术:JSP/Servlet、ASP、PHP
# 常见 Web 服务器
- Tomcat (opens new window)
- Jetty (opens new window)
- Resin (opens new window)
- Apache (opens new window)
- Nginx (opens new window)
- WebSphere (opens new window)
- WebLogic (opens new window)
- JBoss
# Servlet 简介
# 什么是 Servlet
Servlet(Server Applet),即小服务程序或服务连接器。Servlet 是 Java 编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态 Web 内容。
- 狭义的 Servlet 是指 Java 实现的一个接口。
- 广义的 Servlet 是指任何实现了这个 Servlet 接口的类。
Servlet 运行于支持 Java 的应用服务器中。从原理上讲,Servlet 可以响应任何类型的请求,但绝大多数情况下 Servlet 只用来扩展基于 HTTP 协议的 Web 服务器。
# Servlet 和 CGI 的区别
Servlet 技术出现之前,Web 主要使用 CGI 技术。它们的区别如下:
- Servlet 是基于 Java 编写的,处于服务器进程中,他能够通过多线程方式运行 service() 方法,一个实例可以服务于多个请求,而且一般不会销毁;
- CGI(Common Gateway Interface),即通用网关接口。它会为每个请求产生新的进程,服务完成后销毁,所以效率上低于 Servlet。
# Servlet 版本以及主要特性
版本 | 日期 | JAVA EE/JDK 版本 | 特性 |
---|---|---|---|
Servlet 4.0 | 2017 年 10 月 | JavaEE 8 | HTTP2 |
Servlet 3.1 | 2013 年 5 月 | JavaEE 7 | 非阻塞 I/O,HTTP 协议升级机制 |
Servlet 3.0 | 2009 年 12 月 | JavaEE 6, JavaSE 6 | 可插拔性,易于开发,异步 Servlet,安全性,文件上传 |
Servlet 2.5 | 2005 年 10 月 | JavaEE 5, JavaSE 5 | 依赖 JavaSE 5,支持注解 |
Servlet 2.4 | 2003 年 11 月 | J2EE 1.4, J2SE 1.3 | web.xml 使用 XML Schema |
Servlet 2.3 | 2001 年 8 月 | J2EE 1.3, J2SE 1.2 | Filter |
Servlet 2.2 | 1999 年 8 月 | J2EE 1.2, J2SE 1.2 | 成为 J2EE 标准 |
Servlet 2.1 | 1998 年 11 月 | 未指定 | First official specification, added RequestDispatcher, ServletContext |
Servlet 2.0 | JDK 1.1 | Part of Java Servlet Development Kit 2.0 | |
Servlet 1.0 | 1997 年 6 月 |
# Servlet 任务
Servlet 执行以下主要任务:
- 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
- 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
- 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
- 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
- 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。
# Servlet 生命周期
Servlet 生命周期如下:
- 加载 - 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。容器通过类加载器使用 Servlet 类对应的文件加载 servlet;
- 初始化 - Servlet 通过调用 init () 方法进行初始化。
- 服务 - Servlet 调用 service() 方法来处理客户端的请求。
- 销毁 - Servlet 通过调用 destroy() 方法终止(结束)。
- 卸载 - Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
# Servlet API
# Servlet 包
Java Servlet 是运行在带有支持 Java Servlet 规范的解释器的 web 服务器上的 Java 类。
Servlet 可以使用 javax.servlet 和 javax.servlet.http 包创建,它是 Java 企业版的标准组成部分,Java 企业版是支持大型开发项目的 Java 类库的扩展版本。
Java Servlet 就像任何其他的 Java 类一样已经被创建和编译。在您安装 Servlet 包并把它们添加到您的计算机上的 Classpath 类路径中之后,您就可以通过 JDK 的 Java 编译器或任何其他编译器来编译 Servlet。
# Servlet 接口
Servlet 接口定义了下面五个方法:
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
# init() 方法
init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。
Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。
当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
init 方法的定义如下:
public void init() throws ServletException {
// 初始化代码...
}
# service() 方法
service()
方法是执行实际任务的核心方法。Servlet 容器(即 Web 服务器)调用 service()
方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
service()
方法有两个参数:ServletRequest
和 ServletResponse
。ServletRequest
用来封装请求信息,ServletResponse
用来封装响应信息,因此本质上这两个类是对通信协议的封装。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service()
方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet
、doPost
、doPut
,doDelete
等方法。
下面是该方法的特征:
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException{
}
service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。
doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。
# doGet() 方法
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
# doPost() 方法
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
# destroy() 方法
destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:
public void destroy() {
// 终止化代码...
}
# Servlet 和 HTTP 状态码
title: JavaEE Servlet HTTP 状态码 date: 2017-11-08 categories:
- javaee tags:
- javaee
- servlet
- http
# HTTP 状态码
HTTP 请求和 HTTP 响应消息的格式是类似的,结构如下:
- 初始状态行 + 回车换行符(回车+换行)
- 零个或多个标题行+回车换行符
- 一个空白行,即回车换行符
- 一个可选的消息主体,比如文件、查询数据或查询输出
例如,服务器的响应头如下所示:
HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
(Blank Line)
<!doctype ...>
<html>
<head>...</head>
<body>
...
</body>
</html>
状态行包括 HTTP 版本(在本例中为 HTTP/1.1)、一个状态码(在本例中为 200)和一个对应于状态码的短消息(在本例中为 OK)。
以下是可能从 Web 服务器返回的 HTTP 状态码和相关的信息列表:
1**
:信息性状态码2**
:成功状态码- 200:请求正常成功
- 204:指示请求成功但没有返回新信息
- 206:指示服务器已完成对资源的部分 GET 请求
3**
:重定向状态码- 301:永久性重定向
- 302:临时性重定向
- 304:服务器端允许请求访问资源,但未满足条件
4**
:客户端错误状态码- 400:请求报文中存在语法错误
- 401:发送的请求需要有通过 HTTP 认证的认证信息
- 403:对请求资源的访问被服务器拒绝了
- 404:服务器上无法找到请求的资源
5**
:服务器错误状态码- 500:服务器端在执行请求时发生了错误
- 503:服务器暂时处于超负载或正在进行停机维护,现在无法处理请求
# 设置 HTTP 状态码的方法
下面的方法可用于在 Servlet 程序中设置 HTTP 状态码。这些方法通过 HttpServletResponse
对象可用。
序号 | 方法 & 描述 |
---|---|
1 | **public void setStatus ( int statusCode )**该方法设置一个任意的状态码。setStatus 方法接受一个 int(状态码)作为参数。如果您的反应包含了一个特殊的状态码和文档,请确保在使用 PrintWriter 实际返回任何内容之前调用 setStatus。 |
2 | **public void sendRedirect(String url)**该方法生成一个 302 响应,连同一个带有新文档 URL 的 Location 头。 |
3 | **public void sendError(int code, String message)**该方法发送一个状态码(通常为 404),连同一个在 HTML 文档内部自动格式化并发送到客户端的短消息。 |
# HTTP 状态码实例
下面的例子把 407 错误代码发送到客户端浏览器,浏览器会显示 "Need authentication!!!" 消息。
// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
// 扩展 HttpServlet 类
public class showError extends HttpServlet {
// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置错误代码和原因
response.sendError(407, "Need authentication!!!" );
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
现在,调用上面的 Servlet 将显示以下结果:
HTTP Status 407 - Need authentication!!!
type Status report
message Need authentication!!!
description The client must first authenticate itself with the proxy (Need authentication!!!).
Apache Tomcat/5.5.29