Servlet

前言

  • Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求 和 HTTP 服务器上的数据库或应用程序之间的中间层。

  • 使用 Servlet 可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

  • Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。

  • Servlet 为创建基于 web 的应用程序提供了基于组件、独立于平台的方法,可以不受 CGI 程序的性能限制。

  • Servlet 有权限访问所有的 Java API,包括访问企业级数据库的 JDBC API。

  • Servlet 教程(w3cschool)

  • Servlet 教程(runoob)

  • Servlet 快速入门

1、Servlet

  • Servlet(Server Applet),全称 Java Servlet,未有中文译文。是用 Java 编写的服务器端程序。

  • 狭义的 Servlet 是指 Java 语言实现的一个接口,广义的 Servlet 是指任何实现了这个 Servlet 接口的类,一般情况下,人们将 Servlet 理解为后者。

  • 其主要功能在于交互式地浏览和修改数据,生成动态 Web 内容

  • Servlet 运行于支持 Java 的应用服务器中。

  • 从原理上讲,Servlet 可以响应任何类型的请求,但绝大多数情况下 Servlet 只用来扩展基于 HTTP 协议的 Web 服务器

  • 最早支持 Servlet 标准的是 JavaSoft 的 Java Web Server,此后,一些其它的基于 Java 的 Web 服务器开始支持标准的 Servlet。

  • 在浏览器上访问的每一个网页都是一个 Servlet,每个 Servlet 都需要配置一个网址,在 web.xml 文件中配置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app>
    <servlet>
    <servlet-name>HelloServlet</servlet-name> <!-- 服务名称 -->
    <servlet-class>HelloServlet</servlet-class> <!-- 服务 类名 -->
    </servlet>

    <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name> <!-- 服务名称,需和上边的 服务名称 相同 -->
    <url-pattern>/hello</url-pattern> <!-- 页面访问路径,如 http://localhost:8080/hello -->
    </servlet-mapping>
    </web-app>
  • Servlet 执行以下主要任务

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

    • 创建 Web 应用项目。
    • 编写 Servlet 代码。
    • 部署到 Tomcat 中。
  • Tomcat 和 Servlet 关系图

1.1 在 Tomcat 中部署 Servlet 应用

  • 将 Servlet 项目文件放到指定的路径中,如 e:\project\j2ee。

  • 打开 Tomcat conf 目录下的 server.xml 文件。

  • <Host name="localhost" 。。。 下面加一句。path="/" 就表示直接通过 http://localhost:8080/hello 就可以访问网页了。

    1
    <Context path="/" docBase="e:\\project\\j2ee\\web" debug="0" reloadable="false" />
  • 如果设置为如下,那么表示需要通过 http://localhost:8080/servlet/hello 才能访问。

    1
    <Context path="/servlet" docBase="e:\\project\\j2ee\\web" debug="0" reloadable="false" />
  • 注意在 Windows 系统中文件路径是双斜杠,进行 \ 转译,不是单斜杠。

  • 重启 Tomcat,就可以访问了。

  • 参考设置

1.2 获取参数

  • Servlet 获取从浏览器提交的数据。

  • 在执行 doGet() 或者 doPost() 之前,都会先执行 service(),由 service() 方法进行判断,到底该调用 doGet() 还是 doPost()

  • service() 方法

    • 有时候也会直接重写 service() 方法,在其中提供相应的服务,就不用区分到底是 get 还是 post 了。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      import java.io.IOException;
      import java.io.PrintWriter;

      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      public class LoginServlet extends HttpServlet {

      protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      String name = request.getParameter("name");
      String password = request.getParameter("password");

      String html = null;
      if ("admin".equals(name) && "123".equals(password))
      html = "<div style='color:green'>success</div>";
      else
      html = "<div style='color:red'>fail</div>";

      PrintWriter pw = response.getWriter();
      pw.println(html);
      }
      }
  • doGet() 方法

    • 当浏览器使用 get 方式提交数据的时候,servlet 需要提供 doGet() 方法。
    • form 默认的提交方式。
    • 如果通过一个超链访问某个地址。
    • 如果在地址栏直接输入某个地址。
    • ajax 指定使用 get 方式的时候。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      import java.io.IOException;

      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      public class LoginServlet extends HttpServlet {

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      }
      }
  • doPost() 方法

    • 当浏览器使用 post 方式提交数据的时候,servlet 需要提供 doPost() 方法。
    • 在 form 上显示设置 method="post" 的时候。
    • ajax 指定 post 方式的时候。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      import java.io.IOException;

      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      public class LoginServlet extends HttpServlet {

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      String name = request.getParameter("name"); // 获取参数,根据 name 取出对应的账号
      String password = request.getParameter("password"); // 获取参数,根据 password 取出对应的密码

      System.out.println("name:" + name);
      System.out.println("password:" + password);
      }
      }
  • 本地测试

1.3 返回响应

  • Servlet 返回响应数据到浏览器。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String name = request.getParameter("name");
    String password = request.getParameter("password");

    String html = null;
    if ("admin".equals(name) && "123".equals(password)) {
    html = "<div style='color:green'>success</div>";
    } else {
    html = "<div style='color:red'>fail</div>";
    }

    PrintWriter pw = response.getWriter();
    pw.println(html); // 返回响应
    }

1.4 调用流程

  • Servlet 调用流程

  • 1、首先访问 http://127.0.0.1/login.html 打开一个静态的 html 页面,在这个页面中可以通过 form,以 post 的形式提交数据。

  • 2、在 login.html 中,用 form 把账号和密码,提交到 /login 这个路径,并且附带 method="post"

  • 3、Tomcat 接受到一个新的请求 http://127.0.0.1/login,其路径是 /login,接着就到配置文件 web.xml 进行匹配,发现 /login 对应的 Servlet 类是 LoginServlet。

  • 4、Tomcat 定位到了 LoginServlet 后,发现并没有 LoginServlet 的实例存在,于是就调用 LoginServlet 的 public 无参的构造方法 LoginServlet() 实例化一个 LoginServlet 对象以备后续使用。

  • 5、Tomcat 从上一步拿到了 LoginServlet 的实例之后,根据页面 login.html 提交信息的时候带的 method="post",去调用对应的 doPost 方法。

  • 6、在 doPost 方法中,通过参数 request,把页面上传递来的账号和密码信息取出来。

  • 7、接着,根据账号和密码是否正确(判断是否是 admin 和 123),创建不同的 html 字符串。然后把 html 字符串设置在 response 对象上。到这里,Servlet 的工作就做完了。

  • 8、Tomcat 拿到被 Servlet 修改过的 response,根据这个 response 生成 html 字符串,再通过 HTTP 协议将这个 html 字符串,回发给浏览器,浏览器再根据 HTTP 协议获取这个 html 字符串,并渲染在界面上。这样在效果上,浏览器就可以看到 Servlet 中生成的字符串了。

1.5 中文编码

  • 获取中文的参数

    • 在 html 中加上

      1
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    • 在 servlet 进行解码和编码,并且把这句话放在 request.getParameter() 之前

      1
      request.setCharacterEncoding("UTF-8");
  • 返回中文的响应

    • 在 Servlet 中加上以下代码,并且把这句话放在 response.getWriter() 之前

      1
      response.setContentType("text/html; charset=UTF-8");

1.6 生命周期

  • 一个 Servlet 的生命周期由 实例化,初始化,提供服务,销毁,被回收 几个步骤组成。

    1
    实例化 --> 初始化 --> 提供服务 --> 销毁 --> 被回收
  • 无论访问了多少次 Servlet,Servlet 构造方法 只会执行一次,所以 Servlet 是单实例的

  • 无论访问了多少次 Serlvet,init 初始化 只会执行一次。

  • 初始化

    1
    2
    3
    public void init(ServletConfig config) {

    }
  • 提供服务

    1
    2
    3
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
  • 销毁

    1
    2
    3
    public void destroy() {

    }

1.7 页面跳转

  • 页面跳转是开发一个 web 应用经常会发生的事情。比如登录成功或是失败后,分别会跳转到不同的页面。

  • 跳转的方式有两种

    • 服务端跳转:浏览器地址不会发生变化。
    • 客户端跳转:浏览器地址会发生变化。
  • 服务端跳转

    1
    2
    3
    4
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    request.getRequestDispatcher("success.html").forward(request, response);
    }
  • 客户端跳转

    1
    2
    3
    4
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    response.sendRedirect("fail.html");
    }

1.8 自启动

  • Servlet 自启动即伴随着 Tomcat 的启动,自动启动初始化,在初始化方法 init() 中,进行一些业务代码的工作。

  • 在 Tomcat 的 web.xml 中,配置 Servlet 的地方,增加下面一句,取值范围是 1-99,表示启动顺序,数字越小,启动的优先级越高,即表明该 Servlet 会随着 Tomcat 的启动而初始化。

    1
    2
    3
    <servlet>
    <load-on-startup>10</load-on-startup>
    </servlet>
  • 同时,为 Servlet 提供一个 init(ServletConfig) 方法,进行一些业务代码的工作。

    1
    2
    3
    public void init(ServletConfig config){
    System.out.println("init of Hello Servlet");
    }

1.9 上传文件

  • 上传页面有两点需要注意。

    • form 的 method 必须是 post 的,get 不能上传文件。还需要加上 enctype="multipart/form-data" 表示提交的数据是二进制文件。

      1
      <form action="uploadPhoto" method="post" enctype="multipart/form-data">
    • 需要提供 type="file" 的字段进行上传。

      1
      2
      3
      4
      5
      6
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

      <form action="uploadPhoto" method="post" enctype="multipart/form-data">
      上传头像: <input type="file" name="filepath" /> <br>
      <input type="submit" value="上传" />
      </form>

1.10 Request

  • request 对象的类是 HttpServletRequest,提供了很多有实用价值的方法。

  • 常见方法

方法 介绍
request.getRequestURL() 浏览器发出请求时的完整 URL,包括协议 主机名 端口 (如果有)
request.getRequestURI() 浏览器发出请求的资源名部分,去掉了协议和主机名
request.getQueryString() 请求行中的参数部分,只能显示以 GET 方式发出的参数,POST 方式的看不到
request.getRemoteAddr() 浏览器所处于的客户机的 IP 地址
request.getRemoteHost() 浏览器所处于的客户机的主机名
request.getRemotePort() 浏览器所处于的客户机使用的网络端口
request.getLocalAddr() 服务器的 IP 地址
request.getLocalName() 服务器的主机名
request.getMethod() 客户机请求方式,一般是 GET 或者 POST
  • 获取参数
方法 介绍
request.getParameter() 是常见的方法,用于获取单值的参数
request.getParameterValues() 用于获取具有多值的参数,比如注册时候提交的 “hobits”,可以是多选的
request.getParameterMap() 用于遍历所有的参数,并返回 Map 类型
  • 获取头信息
方法 介绍
request.getHeader() 获取浏览器传递过来的头信息。比如 getHeader(“user-agent”) 可以获取浏览器的基本资料
request.getHeaderNames() 获取浏览器所有的头信息名称,根据头信息名称就能遍历出所有的头信息
头信息 介绍
host 主机地址
user-agent 浏览器基本资料
accept 表示浏览器接受的数据类型
accept-language 表示浏览器接受的语言
accept-encoding 表示浏览器接受的压缩方式,是压缩方式,并非编码
connection 是否保持连接
cache-control 缓存时限
  • 服务端传参
方法 介绍
setAttribute 和 getAttribute 可以用来在进行服务端跳转的时候,在不同的 Servlet 之间进行数据共享

1.11 Response

  • response 是 HttpServletResponse 的实例,用于提供给浏览器的响应信息。

  • 设置响应内容

    1
    2
    3
    4
    5
    6
    PrintWriter pw = response.getWriter();

    pw.println();
    pw.append();
    pw.write();
    pw.format();
  • 设置响应格式

    1
    response.setContentType("text/html");
  • 设置响应编码

    1
    2
    response.setContentType("text/html; charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
  • 客户端有两种跳转

    • 301 表示永久性跳转

      1
      response.sendRedirect("fail.html");
    • 302 表示临时跳转

      1
      2
      response.setStatus(301);
      response.setHeader("Location", "fail.html");
  • 设置不使用缓存

    1
    2
    3
    response.setDateHeader("Expires", 0);
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("pragma", "no-cache");

2、动态 Web 项目

3、CRUD

  • CRUD 是常见的页面功能,即我们常说的增删改查。

    • C - Creation 增加
    • R - Retrieve 查询
    • U - Update 修改
    • D - DELETE 删除
  • 与 JDBC 结合,通过 servlet 查询数据库,根据查询结果,得到一个 html 页面,显示数据库中的内容。

  • 使用 Servlet 进行 CRUD 开发的弊端,其中一个比较明显的弊端就是在 Servlet 编写 HTML 代码很痛苦,效率不高,可读性差,难以维护。

  • 最好可以在 HTML 文件里面写 HTML 代码,同时又能在里面调用 Java 的变量,那么这样就需要学习 JSP 了。

  • 本地测试

4、JSON

文章目录
  1. 1. 前言
  2. 2. 1、Servlet
    1. 2.1. 1.1 在 Tomcat 中部署 Servlet 应用
    2. 2.2. 1.2 获取参数
    3. 2.3. 1.3 返回响应
    4. 2.4. 1.4 调用流程
    5. 2.5. 1.5 中文编码
    6. 2.6. 1.6 生命周期
    7. 2.7. 1.7 页面跳转
    8. 2.8. 1.8 自启动
    9. 2.9. 1.9 上传文件
    10. 2.10. 1.10 Request
    11. 2.11. 1.11 Response
  3. 3. 2、动态 Web 项目
  4. 4. 3、CRUD
  5. 5. 4、JSON
隐藏目录