2

JavaWeb 之 Servlet 指南

 11 months ago
source link: https://dunwu.github.io/01.Java/02.JavaEE/01.JavaWeb/01.JavaWeb%E4%B9%8BServlet%E6%8C%87%E5%8D%97.html#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

# JavaWeb 简介

# Web 应用程序

Web,在英语中 web 即表示网页的意思,它用于表示 Internet 主机上供外界访问的资源。

Web 应用程序是一种可以通过 Web 访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件。

Internet 上供外界访问的 Web 资源分为:

  • 静态 web 资源:指 web 页面中供人们浏览的数据始终是不变。常见静态资源文件:html、css、各种图片类型(jpg、png)
  • 动态 web 资源:指 web 页面中供人们浏览的数据是由程序产生的,不同时间点访问 web 页面看到的内容各不相同。常见动态资源技术:JSP/Servlet、ASP、PHP

# 常见 Web 服务器

# 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.02017 年 10 月JavaEE 8HTTP2
Servlet 3.12013 年 5 月JavaEE 7非阻塞 I/O,HTTP 协议升级机制
Servlet 3.02009 年 12 月JavaEE 6, JavaSE 6可插拔性,易于开发,异步 Servlet,安全性,文件上传
Servlet 2.52005 年 10 月JavaEE 5, JavaSE 5依赖 JavaSE 5,支持注解
Servlet 2.42003 年 11 月J2EE 1.4, J2SE 1.3web.xml 使用 XML Schema
Servlet 2.32001 年 8 月J2EE 1.3, J2SE 1.2Filter
Servlet 2.21999 年 8 月J2EE 1.2, J2SE 1.2成为 J2EE 标准
Servlet 2.11998 年 11 月未指定First official specification, added RequestDispatcher, ServletContext
Servlet 2.0JDK 1.1Part of Java Servlet Development Kit 2.0
Servlet 1.01997 年 6 月

# Servlet 任务

Servlet 执行以下主要任务:

  • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
  • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
  • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
  • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

# Servlet 生命周期

img

img

Servlet 生命周期如下:

  1. 加载 - 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。容器通过类加载器使用 Servlet 类对应的文件加载 servlet;
  2. 初始化 - Servlet 通过调用 init () 方法进行初始化。
  3. 服务 - Servlet 调用 service() 方法来处理客户端的请求。
  4. 销毁 - Servlet 通过调用 destroy() 方法终止(结束)。
  5. 卸载 - Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

# Servlet API

# Servlet 包

Java Servlet 是运行在带有支持 Java Servlet 规范的解释器的 web 服务器上的 Java 类。

Servlet 可以使用 javax.servletjavax.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() 方法有两个参数:ServletRequestServletResponseServletRequest 用来封装请求信息,ServletResponse 用来封装响应信息,因此本质上这两个类是对通信协议的封装。

每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGetdoPostdoPutdoDelete 等方法。

下面是该方法的特征:

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/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

# 参考资料


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK