动态网站开发学习笔记04:Servlet基础

零、本节学习目标

掌握Servlet的基本概念
掌握Servlet的特点及其接口
熟悉使用IDEA工具开发Servlet
掌握Servlet的配置以及Servlet的生命周期
掌握ServletConfig和ServletContext接口的使用
掌握HttpServletRequest对象的使用
掌握HttpServletResponse对象的使用

  • 随着Web应用业务需求的增多,动态Web资源的开发变得越来越重要。目前,很多公司都提供了开发动态Web资源的相关技术,其中比较常见的有ASP、PHP、JSP和Servlet等。基于Java的动态Web资源开发,SUN公司提供了Servlet和JSP两种技术。本节将针对Servlet技术的相关知识进行详细讲解。

一、Servlet基础

目标:掌握Servlet的概念、特点和接口

(一)Servlet概述

1、Servlet是什么
Servlet是运行在Web服务器端的Java应用程序,它使用Java语言编写。与Java程序的区别是,Servlet 对象主要封装了对HTTP请求的处理,并且它的运行需要Servlet容器的支持。在Java Web应用方面,Servlet 的应用占有十分重要的地位,它在Web请求的处理功能方面也非常强大。
2、Servlet容器
Servlet由Servlet容器提供,Servlet容器是指提供了Servlet 功能的服务器(本讲稿指Tomcat)。Servlet容器将Servlet动态地加载到服务器上。与HTTP 协议相关的Servlet使用HTTP请求和HTTP响应与客户端进行交互。因此,Servlet容器支持所有HTTP协议的请求和响应。
3、Servlet应用程序的体系结构
Servlet的请求首先会被HTTP服务器(如Apache)接收,HTTP服务器只负责静态HTML页面的解析,对于Servlet的请求转交给Servlet容器,Servlet容器会根据web.xml文件中的映射关系,调用相应的Servlet,Servlet将处理的结果返回给Servlet容器,并通过HTTP服务器将响应传输给客户端。

(二)Servlet的特点

Servlet使用Java语言编写,它不仅具有Java 语言的优点,而且还对Web的相关应用进行了封装,同时Servlet容器还提供了对应用的相关扩展,无论是在功能、性能、安全等方面都十分优秀。
1、功能强大
Servlet采用Java语言编写,它可以调用Java API中的对象及方法,此外,Servlet对象对Web应用进行了封装,提供了Servlet对Web应用的编程接口,还可以对HTTP请求进行相应的处理,如处理提交数据、会话跟踪、读取和设置HTTP头信息等。由于Servlet既拥有Java 提供的API,而且还可以调用Servlet封装的Servlet API编程接口,所以,它在业务功能方面十分强大。
2、可移植
Java语言是跨越平台的,所谓跨越平台是指程序的运行不依赖于操作系统平台,它可以运行到多个系统平台中,如目前常用的操作系统Windows、Linux和UNIX等。
3、性能高效
Servlet对象在Servlet容器启动时被初始化,当Servlet对象第一次被请求时,Servlet 容器将Servlet对象实例化,此时Servlet对象驻存于内存中。如果存在多个请求,Servlet 不会再被实例化,仍然由第一次被实例化的Servlet对象处理其他请求。每一个请求是一个线程,而不是一个进程。
4、安全性高
Servlet使用了Java的安全框架,同时Servlet容器还可以为Servlet提供额外的安全功能,它的安全性是非常高的。
5、可扩展
Java语言是面向对象的编程语言, Servlet由Java语言编写,所以它具有面向对象的优点。在业务逻辑处理中,可以通过封装、继承等特性扩展实际的业务需要。

(三)Servlet接口

1、Servlet接口
针对Servlet技术的开发,SUN公司提供了一系列接口和类,其中最重要的是javax.servlet.Servlet接口。Servlet就是一种实现了Servlet接口的类,它由Web容器负责创建并调用,用于接收和响应用户的请求。
2、Servlet接口的方法
3、Servlet接口中生命周期的方法
在Servlet接口中的5个方法中,其中init()、service()和destroy()这三个方法可以表现Servlet的生命周期,它们会在某个特定的时刻被调用。需要注意的是,Servlet容器指的就是Web服务器。
4、Servlet接口的实现类
针对Servlet接口,SUN公司提供了两个默认的接口实现类:GenericServlet和HttpServlet。GenericServlet是一个抽象类,该类为Servlet接口提供了部分实现,它并没有实现HTTP请求处理。HttpServlet是GenericServlet的子类,它继承了GenericServlet的所有方法,并且为HTTP请求中的POST、GET等类型提供了具体的操作方法。
5、HttpServlet类的常用方法及功能

二、Servlet开发入门

(一)实现第一个Servlet程序

目标:掌握如何使用IDEA工具开发Servlet程序
1、使用IDEA完成Servlet的开发
在实际开发中,通常都会使用IDEA(或Eclipse等)工具完成Servlet的开发,我们使用IDEA完成Servlet的开发,因为IDEA不仅会自动编译Servlet,还会自动创建web.xml文件信息,完成Servlet虚拟路径的映射。

(1)新建Web项目

选择IDEA主页的“Create New Project”选项,进入新建项目的界面。
在这里插入图片描述

在New Projec界面中,选择左侧栏的“Java”选项,然后勾选”Web Application”选项。选择完毕之后,单击”Next”按钮进入填写项目信息的界面。
在这里插入图片描述

在New Projec界面中,”Project name”选项用于指项目的名称,”Project localtion”选项用于指定Web项目的根目录。项目的根目录设置为D:\web_work\chapter04,将WebDemo作为Web项目的名称。设置完成之后,单击“Finish”按钮,进入开发界面。
在这里插入图片描述

修改Artifact名称 - WebDemo
在这里插入图片描述

编辑Tomcat服务器配置
在这里插入图片描述

切换到【Server】选项卡
在这里插入图片描述

启动服务器,查看效果
在这里插入图片描述

(2)创建Servlet类

新建net.huawei.servlet包
在这里插入图片描述

在net.huawei.servlet包里创建ServletDemo01类
在这里插入图片描述
在这里插入图片描述

此时IDEA工具会自动生成Servlet代码
在这里插入图片描述

为了更好地演示Servlet的运行效果,接下来在ServletDemo01的doGet()和doPost()方法中添加一些代码。在@WebServlet注解里设置urlPatterns属性值:urlPatterns = “/demo01”
在这里插入图片描述

package net.huawei.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "ServletDemo01", urlPatterns = "/demo01")
public class ServletDemo01 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取字符输出流
        PrintWriter out = response.getWriter();
        // 输出信息
        out.print("<h1>Hello Servlet World~</h1>");
    }

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

其实,Servlet本质上就是Java程序里嵌入了HTML页面
(3)启动Servlet
启动服务器,显示首页
在这里插入图片描述

在页面访问ServletDemo01类的url地址“localhost:8080/WebDemo/demo01”

对应关系图
在这里插入图片描述

希望显示红色消息,并且居中显示,那么就要用到样式

在这里插入图片描述

2、课堂练习 - 创建Web项目,利用Servlet显示个人信息

创建Java Enterprise项目
在这里插入图片描述

设置项目名称与保存位置
在这里插入图片描述

单击【Finish】按钮
在这里插入图片描述

查看Artifacts的名称
在这里插入图片描述

将名称改为ShowInfo
在这里插入图片描述

配置tomcat服务器
在这里插入图片描述

在Deployment里删除ShowInfo后重新添加
在这里插入图片描述

切换到【Server】选项卡,查看URL
在这里插入图片描述

启动tomcat服务器,查看效果
在这里插入图片描述

修改首页文件,以表格形式显示个人信息
在这里插入图片描述

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>个人信息</title>
    </head>
    <body>
        <table style="text-align: center" border="1" align="center" cellpadding="5">
            <tr>
                <td>学号</td>
                <td>姓名</td>
                <td>性别</td>
                <td>年龄</td>
                <td>专业</td>
                <td>班级</td>
                <td>手机</td>
            </tr>
            <tr>
                <td>20210201</td>
                <td>陈燕文</td>
                <td></td>
                <td>18</td>
                <td>软件技术专业</td>
                <td>2021软件2班</td>
                <td>15890456780</td>
            </tr>
        </table>
    </body>
</html>

启动服务器,查看结果
在这里插入图片描述

创建net.huawei.servlet包,在包里创建InfoServlet类
在这里插入图片描述

package net.huawei.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "InfoServlet", urlPatterns = "/info")
public class InfoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取字符输出流
        PrintWriter out = response.getWriter();
        // 往客户端输出信息
        out.print("<!DOCTYPE html>");
        out.print("<html>");
            out.print("<head>");
                out.print("<meta charset='UTF-8'>");
                out.print("<title>个人信息</title>");
            out.print("</head>");
            out.print("<body style='text-align: center'>");
                out.print("<table border='1' align='center' cellpadding='5'>");
                    out.print("<tr>");
                        out.print("<td>学号</td>");
                        out.print("<td>姓名</td>");
                        out.print("<td>性别</td>");
                        out.print("<td>年龄</td>");
                        out.print("<td>专业</td>");
                        out.print("<td>班级</td>");
                        out.print("<td>手机</td>");
                    out.print("</tr>");
                    out.print("<tr>");
                        out.print("<td>20210201</td>");
                        out.print("<td>陈燕文</td>");
                        out.print("<td></td>");
                        out.print("<td>18</td>");
                        out.print("<td>软件技术专业</td>");
                        out.print("<td>2021软件2班</td>");
                        out.print("<td>15890456780</td>");
                        out.print("</tr>");
                out.print("</table>");
            out.print("</body>");
        out.print("</html>");
    }

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

启动tomcat服务器,访问http://localhost:8080/ShowInfo/info
在这里插入图片描述

页面出现中文乱码,需要设置字符编码(要查看Chrome浏览器默认的字符编码)
在这里插入图片描述

设置响应对象字符编码为UTF-8,与浏览器当前采用的字符编码保持一致
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/ShowInfo/info
在这里插入图片描述

无论浏览器当前采用什么字符编码,通过设置响应对象内容类型来要求浏览器采用指定的字符编码
A

重启tomcat服务器,访问http://localhost:8080/ShowInfo/info
在这里插入图片描述

查看浏览器当前使用的字符编码,已经被改成GBK了

在这里插入图片描述

(二)Servlet的配置

目标:掌握完成Servlet的配置的两种方式:通过Web应用的配置文件web.xml来,通过@WebServlet注解来完成Servlet的配置
若想让Servlet正确地运行在服务器中并处理请求信息,必须进行适当的配置,关于Servlet的配置主要有两种方式,分别是通过Web应用的配置文件web.xml来完成配置和使用@WebServlet注解的方式完成。

1、使用web.xml配置Servlet

在web.xml文件中,通过标签进行注册,在标签下包含若干个子元素。

把Servlet映射到URL地址,使用标签进行映射,使用子标签指定要映射的Servlet名称,名称要和之前在标签下注册的相同;使用子标签映射URL地址,地址前必须加“/”,否则访问不到。
在这里插入图片描述

在部署描述文件web.xml里注册了Servlet,那么就可以注释掉InfoServlet类上的注解
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/ShowInfo/info
在这里插入图片描述

2、@WebServlet注解属性

@WebServlet 注解用于代替web.xml文件中的等标签,该注解将会在项目部署时被容器处理,容器将根据具体的属性配置将相应的类部署为Servlet。为此,@WebServlet注解提供了一些属性。

@WebServlet注解可以标注在任意一个继承了HttpServlet类的类之上,属于类级别的注解。下面使用@WebServlet注解标注InfoServlet类。

在这里插入图片描述

在web.xml文件里注释掉对InfoServlet的注册标签
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/ShowInfo/info
在这里插入图片描述

使用@WebServlet注解将InfoServlet类标注为一个Servlet。@WebServlet注解中的name属性值用于指定servlet的name属性,等价于,如果没有设置@WebServlet的name属性,其默认值是Servlet的类完整名称。urlPatterns属性值用于指定一组servlet的url的匹配模式,等价于标签。如果需要在@WebServlet注解中设置多个属性,属性之间用逗号隔开。通过@WebServlet注解能极大地简化了Servlet的配置步骤,降低了开发人员的开发难度。

3、给一个Servlet配置多个url

好比一个人有多个对外联系方式
在这里插入图片描述

启动服务器,访问http://localhost:8080/ShowInfo/info
在这里插入图片描述

访问http://localhost:8080/ShowInfo/message
在这里插入图片描述

(三)Servlet的生命周期

目标:掌握Servlet的三个生命周期,初始化阶段、运行阶段和销毁阶段

1、Servle生命周期 - 初始化阶段

当客户端向Servlet容器发出HTTP请求访问Servlet时,Servlet容器首先会解析请求,检查内存中是否已经有了该Servlet对象,如果有,直接使用该Servlet对象;如果没有,就创建Servlet实例对象,然后通过调用init()方法完成Servlet的初始化。需要注意的是,在Servlet的整个生命周期内,它的init()方法只被调用一次。

2、Servlet生命周期 - 运行阶段

这是Servlet生命周期中最重要的阶段,在这个阶段,Servlet容器会为客户端请求创建代表HTTP请求的ServletRequest对象和代表HTTP响应的ServletResponse对象,然后将它们作为参数传递给Servlet的service()方法。service()方法从ServletRequest对象中获得客户端请求信息并处理该请求,通过ServletResponse对象生成响应结果。在Servlet的整个生命周期内,对于Servlet的每一次访问请求,Servlet容器都会调用一次Servlet的service()方法,并且创建新的ServletRequest和ServletResponse对象,也就是说,service()方法在Servlet的整个生命周期中会被调用多次。

3、Servlet生命周期 - 销毁阶段

当服务器关闭或web应用被移除出容器时,Servlet随着web应用的销毁而销毁。在销毁Servlet之前,Servlet容器会调用Servlet的destroy()方法,以便让Servlet对象释放它所占用的资源。在Servlet的整个生命周期中,destroy()方法也只被调用一次。需要注意的是,Servlet对象一旦创建就会驻留在内存中等待客户端的访问,直到服务器关闭,或web应用被移除出容器时Servlet对象才会销毁。

4、案例演示Servlet生命周期

在WebDemo项目中创建ServletDemo02类,在ServletDemo02类中编写init()方法和destroy()方法并重写service()方法,用来案例演示Servlet生命周期方法的执行效果。
在这里插入图片描述

package net.huawei.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


@WebServlet(name = "ServletDemo02", value = "/demo02")
public class ServletDemo02 extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("init()方法被调用……");
    }

    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("service()方法被调用……");
        response.setContentType("text/html; charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("<h1>演示Servlet生命周期~</h1>");
    }

    @Override
    public void destroy() {
        System.out.println("destroy()方法被调用……");
    }
}

启动tomcat服务器,访问http://localhost:8080/WebDemo/demo02
在这里插入图片描述

刷新浏览器两次,两次访问ServletDemo02,查看tomcat控制台的打印结果
在这里插入图片描述

init()方法只在第一次访问时执行,service()方法则在每次访问时都被执行。

如果想将ServletDemo02移除,可以在IDEA中停止WebDemo项目,此时,Servlet容器会调用ServletDemo02的destroy()方法,在IDEA控制台打印出“destroy()方法被调用……”信息。
在这里插入图片描述

打个比方:我们只能诞生一次(init()方法),死亡一次(destroy()方法),中间可以换很多次工作,给社会提供不同的服务(service()方法)。

三、ServletConfig和ServletContext

(一)ServletConfig接口

目标:掌握如何使用ServletConfig获取配置信息的方法
1、ServletConfig接口
在Servlet运行期间,经常需要一些配置信息,例如,文件使用的编码等,这些信息都可以在@WebServlet注解的属性中配置。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息封装到一个ServletConfig对象中,通过调用init(ServletConfig config)方法将ServletConfig对象传递给Servlet。ServletConfig定义了一系列获取配置信息的方法。

2、案例演示ServletConfig方法调用
以getInitParameter()方法为例讲解ServletConfig方法的调用
在WebDemo项目的net.huawei.servlet包里创建ServletDemo03类
在这里插入图片描述

package net.huawei.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

@WebServlet(name = "ServletDemo03", urlPatterns = "/demo03",
    initParams = {@WebInitParam(name="encoding", value = "utf-8"),
                  @WebInitParam(name="text-color", value = "red"),
                  @WebInitParam(name="font-size", value= "25")})
public class ServletDemo03 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 设置响应对象内容类型
        response.setContentType("text/html; charset=utf-8");
        // 获取打印输出流
        PrintWriter out = response.getWriter();
        // 获取Servlet配置对象
        ServletConfig config = getServletConfig();
        // 获取初始化参数名枚举对象
        Enumeration<String> initParams = config.getInitParameterNames();
        // 遍历初始化参数名枚举对象,输出参数名及其值
        while (initParams.hasMoreElements()) {
            String initParam = initParams.nextElement();
            out.print(initParam + " : " + config.getInitParameter(initParam) + "<br />");
        }
    }

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


启动tomcat服务器,访问http://localhost:8080/WebDemo/demo03
在这里插入图片描述

(二)ServletContext接口

目标:掌握ServletContext接口的使用方法
1、获取Web应用程序的初始化参数
当Servlet容器启动时,会为每个Web应用创建一个唯一的ServletContext对象代表当前Web应用。ServletContext对象不仅封装了当前Web应用的所有信息,而且实现了多个Servlet之间数据的共享。
在web.xml文件中,可以配置Servlet的初始化信息,还可以配置整个Web应用的初始化信息。Web应用初始化参数的配置方式具体如下所示。

<context-param>
      <param-name>参数名</param-name>
      <param-value>参数值</param-value>
</context-param>
<context-param>
      <param-name>参数名</param-name>
      <param-value>参数值</param-value>
</context-param>

元素位于根元素中,它的子元素和分别用来指定参数的名字和参数值。可以通过调用ServletContext接口中定义的getInitParameterNames()和getInitParameter(String name)方法,分别获取参数名和参数值。
2、案例演示获取Web应用的容器初始化参数
在WebDemo项目的web.xml文件中,配置容器初始化参数信息和Servlet信息

在这里插入图片描述

package net.huawei.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

/**
 * 功能:获取Web应用的容器初始化参数
 * 作者:华卫
 * 日期:2023年03月31日
 */
@WebServlet(name = "ServletDemo04", urlPatterns = "/demo04")
public class ServletDemo04 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 设置响应对象内容类型
        response.setContentType("text/html; charset=utf-8");
        // 获取打印输出流
        PrintWriter out = response.getWriter();
        // 获取Servlet容器对象
        ServletContext context = getServletContext();
        // 获取容器的初始化参数名枚举对象
        Enumeration<String> paramNames = context.getInitParameterNames();
        // 通过循环遍历显示全部参数名与参数值
        while (paramNames.hasMoreElements()) {
            // 获取参数名
            String name = paramNames.nextElement();
            // 按参数名获取参数值
            String value = context.getInitParameter(name);
            // 输出参数名和参数值
            out.print(name + " : " + value + "<br />");
        }
    }

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

启动tomcat服务器,访问http://localhost:8080/WebDemo/demo04
在这里插入图片描述

3、实现多个Servlet对象共享数据
由于一个Web应用中的所有Servlet共享同一个ServletContext对象,所以ServletContext对象的域属性可以被该Web应用中的所有Servlet访问。ServletContext接口中定义了用于增加、删除、设置ServletContext域属性的四个方法。

4、案例演示多个Servlet对象共享数据
在net.huawei.servlet包里创建ServletDemo05类

在这里插入图片描述

package net.huawei.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 功能:写入域属性
 * 作者:华卫
 * 日期:2023年03月31日
 */
@WebServlet(name = "ServletDemo05", urlPatterns = "/demo05")
public class ServletDemo05 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 设置响应对象内容类型
        response.setContentType("text/html; charset=utf-8");
        // 获取Servlet容器对象
        ServletContext context = getServletContext();
        // 写入域属性
        context.setAttribute("id", "20210201");
        context.setAttribute("name", "陈雅雯");
        context.setAttribute("gender", "女");
        context.setAttribute("age", "18");
        context.setAttribute("major", "软件技术专业");
        context.setAttribute("class", "2021软件2班");
        context.setAttribute("telephone", "15890903456");
        // 获取打印输出流
        PrintWriter out = response.getWriter();
        // 输出提示信息
        out.print("<h3>成功地写入了域属性~</h3>");
    }

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

在net.huawei.servlet包里创建ServletDemo06类

在这里插入图片描述

启动tomcat服务器,先访问http://localhost:8080/WebDemo/demo05
在这里插入图片描述

再访问http://localhost:8080/WebDemo/demo06
在这里插入图片描述

有很多域属性不是我们写入的,如果我们只想显示我们写入的域属性,那么我们就要修改一下ServletDemo06的代码
在这里插入图片描述

重启服务器,访问http://localhost:8080/WebDemo/demo05
在这里插入图片描述

再访问http://localhost:8080/WebDemo/demo06
在这里插入图片描述

5、读取Web应用下的资源文件
ServletContext接口定义了一些读取Web资源的方法,这些方法是依靠Servlet容器来实现的。Servlet容器根据资源文件相对于Web应用的路径,返回关联资源文件的IO流、资源文件在文件系统的绝对路径等。

6、案例演示读取Web应用下的资源文件
在net.huawei.servlet包里创建属性文件 - college.properties
在这里插入图片描述

name = 泸州职业技术学院
address = 泸州市龙马潭区长桥路2号
secretary = 何杰
president = 谢鸿全

在net.huawei.servlet包里创建ServletDemo07类
在这里插入图片描述

启动tomcat服务器,访问http://localhost:8080/WebDemo/demo07

在这里插入图片描述

属性文件的路径问题
在这里插入图片描述

读取属性文件得到的字节流编码是ISO-8859-1,需要做一个转码处理
在这里插入图片描述

重启tomcat服务器,先访问http://localhost:8080/WebDemo/demo07
在这里插入图片描述

在Web项目开发中开发者可能需要获取资源的绝对路径。通过调用getRealPath(String path)方法获取资源文件的绝对路径。

在net.huawei.servlet包里创建ServletDemo08类
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/demo08
在这里插入图片描述

四、HttpServletResponse对象

(一)发送状态码相关的方法

目标:掌握HttpServletResponse接口定义的3个发送状态码的方法
当Servlet向客户端回送响应消息时,需要在响应消息中设置状态码,状态码代表着客户端请求服务器的结果。为此,HttpServletResponse接口定义了3个发送状态码的方法。
1、HttpServletResponse接口—setStatus(int status)方法
setStatus(int status)方法用于设置HTTP响应消息的状态码,并生成响应状态行。由于响应状态行中的状态描述信息直接与状态码相关,而HTTP版本由服务器确定,所以,只要通过setStatus(int status)方法设置了状态码,即可实现状态行的发送。例如,正常情况下,Web服务器会默认产生一个状态码为200的状态行。
2、HttpServletResponse接口—sendError(int sc)方法
sendError(int sc)方法用于发送表示错误信息的状态码,例如,404状态码表示找不到客户端请求的资源。
3、HttpServletResponse接口—sendError(int code,String message)方法
sendError(int code, String message)方法除了设置状态码,还会向客户端发出一条错误信息。服务器默认会创建一个HTML格式的错误服务页面作为响应结果,其中包含参数message指定的文本信息,这个HTML页面的内容类型为“text/html”,保留cookies和其他未修改的响应头信息。如果一个对应于传入的错误码的错误页面已经在web.xml中声明,那么这个声明的错误页面会将优先建议的message参数服务于客户端。

(二)发送响应头相关的方法

目标:掌握HttpServletResponse接口设置HTTP响应头字段的方法

(三)发送响应消息体相关的方法

目标:掌握发送响应消息体相关的方法getOutputStream()和getWriter()
由于在HTTP响应消息中,大量的数据都是通过响应消息体传递的,所以,ServletResponse遵循IO流传递大量数据的设计理念。在发送响应消息体时,定义了两个与输出流相关的方法。
1、getOutputStream()方法
getOutputStream()方法所获取的字节输出流对象为ServletOutputStream类型。由于ServletOutputStream是OutputStream的子类,它可以直接输出字节数组中的二进制数据。所以,要想输出二进制格式的响应正文,就需要调用getOutputStream()方法。
2、getWriter()方法
getWriter()方法所获取的字符输出流对象为PrintWriter类型。由于PrintWriter类型的对象可以直接输出字符文本内容,所以,要想输出内容为字符文本的网页文档,需要调用getWriter()方法。
3、案例演示发送响应消息体
创建net.huawei.response包
在这里插入图片描述

在net.huawei.response包里创建PrintServlet01类

在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/print01
在这里插入图片描述

在net.huawei.response包里创建PrintServlet02类
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/print02
在这里插入图片描述

为了解决页面中文乱码问题,要修改代码
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/print02
在这里插入图片描述

五、HttpServletResponse应用

(一)实现请求重定向

目标:掌握HttpServletResponse接口的sendRedirect()方法,实现请求重定向
在某些情况下,针对客户端的请求,一个Servlet类可能无法完成全部工作。这时,可以使用请求重定向来完成。所谓请求重定向,指的是Web服务器接收到客户端的请求后,可能由于某些条件限制,不能访问当前请求URL所指向的Web资源,而是指定了一个新的资源路径,让客户端重新发送请求。
1、HttpServletResponse接口—sendRedirect()方法
为了实现请求重定向,HttpServletResponse接口定义了一个sendRedirect()方法,该方法用于生成302响应码和Location响应头,从而通知客户端重新访问Location响应头中指定的URL。
sendRedirect()方法的完整声明:public void sendRedirect(java.lang.String location) throws java.io.IOException
需要注意的是,参数location可以使用相对URL,Web服务器会自动将相对URL翻译成绝对URL,再生成Location头字段。
sendRedirect()方法的工作原理

2、案例演示实现请求重定向
创建登录页面 - login.html
在这里插入图片描述

创建欢迎页面 - welcome.html
在这里插入图片描述

在net.huawei.response包里创建LoginServlet类,处理用户登录请求
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/login.html
在这里插入图片描述

在login.html页面填写用户名“howard”,密码“903213”
在这里插入图片描述

单击登录按钮,跳转到欢迎页面
在这里插入图片描述

(二)动手实践:解决中文输出乱码问题

目标:掌握如何解决中文输出乱码问题
1、中文乱码问题
由于计算机中的数据都是以二进制形式存储的,所以,当传输文本时,就会发生字符和字节之间的转换。字符与字节之间的转换是通过查码表完成的,将字符转换成字节的过程称为编码,将字节转换成字符的过程称为解码,如果编码和解码使用的码表不一致,就会导致乱码问题。
2、案例演示解决乱码问题
在net.huawei.response包里创建ChineseServlet类

在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/chinese
在这里插入图片描述

浏览器显示的内容都是“???~”,说明发生了乱码问题。此处产生乱码的原因是response对象的字符输出流在编码时,采用的是ISO-8859-1的字符码表,该码表并不兼容中文,会将“欢迎访问泸州职业技术学院”编码为“63 63 63 63 63 63 63 63 63 63 63 63”(在ISO-8859-1的码表中查不到的字符就会显示63)。当浏览器对接收到的数据进行解码时,会采用默认的码表GB2312,将“63 ”解码为“?”,因此,浏览器将“欢迎访问泸州职业技术学院”十二个字符显示成了“???”。

解决页面乱码问题

HttpServletResponse接口提供了一个setCharacterEncoding()方法,该方法用于设置字符的编码方式,接下来对ChineseServlet类进行修改,在代码String data = “欢迎访问泸州职业技术学院~”;前增加一行代码,设置字符编码使用的码表为utf-8。
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/chinese
在这里插入图片描述

浏览器中显示的乱码虽然不是“???”,但也不是需要输出的“欢迎访问泸州职业技术学院”,这是由于浏览器解码错误导致的。response对象的字符输出流设置的编码方式为UTF-8,而浏览器使用的解码方式是GBK。
在这里插入图片描述

将response对象的字符输出流设置的编码方式改为GBK
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/chinese
在这里插入图片描述

一种更好的方法来解决页面中文乱码问题,直接要求浏览器按照某种字符编码来显示中文
在这里插入图片描述

response.setContentType(“text/html;charset=utf-8”);让浏览器采用utf-8字符编码

重启tomcat服务器,访问http://localhost:8080/WebDemo/chinese
在这里插入图片描述

当然也可以换种方式来解决

六、HttpServletRequest对象

(一)获取请求行信息的相关方法

目标:掌握使用HttpServletRequest接口中的方法获取请求行
1、相关方法

2、案例演示
创建net.huawei.request包,在包里创建RequestLineServlet类
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/request
在这里插入图片描述

getContextPath: /WebDemo + getServletPath: /request = getRequestURI: /WebDemo/request
getScheme: http + “:” + getServerName: localhost + “:” + getServerPort: 8080 + getRequestURI: /WebDemo/request = getRequestURL: http://localhost:8080/WebDemo/request
URI: Uniform Resource Identifier 统一资源标识符
URL: Uniform Resource Locator 统一资源定位器
演示请求字符串
在这里插入图片描述

重启tomcat服务器,访问http://localhost:8080/WebDemo/request?username=howard&password=903213

还可以将查询字符串继续按=进行拆分

(二)获取请求头的相关方法
目标:掌握使用HttpServletRequest接口获取HTTP请求头字段的方法
1、相关方法
方法声明 功能描述
String getHeader(String name) 该方法用于获取一个指定头字段的值,如果请求消息中没有包含指定的头字段,getHeader()方法返回null;如果请求消息中包含有多个指定名称的头字段,getHeader()方法返回其中第一个头字段的值
Enumeration getHeaders(String name) 该方法返回一个Enumeration集合对象,该集合对象由请求消息中出现的某个指定名称的所有头字段值组成。在多数情况下,一个头字段名在请求消息中只出现一次,但有时候可能会出现多次
Enumeration getHeaderNames() 该方法用于获取一个包含所有请求头字段的Enumeration对象
int getIntHeader(String name) 该方法用于获取指定名称的头字段,并且将其值转为int类型。需要注意的是,如果指定名称的头字段不存在,返回值为-1;如果获取到的头字段的值不能转为int类型,将发生NumberFormatException异常
long getDateHeader(String name) 该方法用于获取指定头字段的值,并将其按GMT时间格式转换成一个代表日期/时间的长整数,这个长整数是自1970年1月1日0点0分0秒算起的以毫秒为单位的时间值
String getContentType() 该方法用于获取Content-Type头字段的值,结果为String类型
int getContentLength() 该方法用于获取Content-Length头字段的值,结果为int类型
String getCharacterEncoding() 该方法用于返回请求消息的实体部分的字符集编码,通常是从Content-Type头字段中进行提取,结果为String类型
2、案例演示
在net.huawei.request包里创建RequestHeadersServlet类

package net.huawei.request;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

/**

  • 功能:演示获取请求头的信息

  • 作者:华卫

  • 日期:2023年04月14日
    */
    @WebServlet(name = “RequestHeaderServlet”, urlPatterns = “/header”)
    public class RequestHeaderServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    // 设置响应体内容类型
    response.setContentType(“text/html; charset=utf-8”);
    // 获取字符输出流
    PrintWriter out = response.getWriter();
    // 获取请求头名枚举对象
    Enumeration headerNames = request.getHeaderNames();
    // 遍历所有请求头,并通过getHeader()方法获取一个指定名称的头字段
    while (headerNames.hasMoreElements()) {
    // 获取头字段名称
    String headerName = headerNames.nextElement();
    // 输出头字段名称及其值
    out.println(headerName + " : " + request.getHeader(headerName) + “
    ”);
    }
    }

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

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
重启tomcat服务器,访问http://localhost:8080/WebDemo/header

按F12键,通过开发者工具查看请求头信息

(三)请求转发
目标:掌握使用HttpServletRequest接口将请求转发
1、getRequestDispatcher()方法
Servlet之间可以相互跳转,利用Servlet的跳转可以很容易地把一项任务按模块分开,例如,使用一个Servlet实现用户登录,然后跳转到另外一个Servlet实现用户资料修改。Servlet的跳转要通过RequestDispatcher接口的实例对象实现。HttpServletRequest接口提供了getRequestDispatcher()方法用于获取RequestDispatcher对象,getRequestDispatcher()方法的具体格式: RequestDispatcher getRequestDispatcher(String path)
getRequestDispatcher()方法返回封装了某条路径所指定资源的RequestDispatcher对象。其中,参数 path 必须以“/”开头,用于表示当前 Web 应用的根目录。需要注意的是,WEB-INF目录中的内容对RequestDispatcher对象也是可见的。因此,传递给 getRequestDispatcher(String path) 方法的资源可以是 WEB-INF 目录中的文件。
2、forward()方法
获取到RequestDispatcher对象后,如果当前 Web 资源不想处理请求,RequestDispatcher接口提供了一个forward()方法,该方法可以将当前请求传递给其他 Web 资源对这些信息进行处理并响应给客户端,这种方式称为请求转发。forward()方法的具体格式:forward(ServletRequest request,ServletResponse response)
forward()方法用于将请求从一个 Servlet 传递给另一个 Web 资源。在 Servlet 中,可以对请求做一个初步处理,然后通过调用forward()方法,将请求传递给其他资源进行响应。需要注意的是,该方法必须在响应提交给客户端之前被调用,否则将抛出 IllegalStateException 异常。
当浏览器访问Servlet1时,可以通过forward()方法将请求转发给其他Web资源,其他Web资源处理完请求后,直接将响应结果返回到浏览器。

3、案例演示请求转发
在net.huawei.request包里创建RequestForwardServlet类,将数据保存在request对象里,然后转发给另一个Servlet来处理

在net.huawei.request包里创建ResultServlet类,用于获取RequestForwardServlet类中存储在request对象中的数据并输出

对应关系图

重启tomcat服务器,访问http://localhost:8080/WebDemo/forward

注意:地址栏中显示的仍然是RequestForwardServlet的请求路径,但是浏览器却显示出了ResultServlet中要输出的内容。这是因为请求转发是发生在服务器内部的行为,从RequestForwardServlet到ResultServlet属于一次请求,在一次请求中可以使用request 属性进行数据共享(同一请求转发)。

(四)获取请求参数
目标:掌握使用HttpServletRequest接口获取请求参数
1、相关方法
方法声明 功能描述
String getParameter(String name) 该方法用于获取某个指定名称的参数值,如果请求消息中没有包含指定名称的参数,getParameter()方法返回null;如果指定名称的参数存在但没有设置值,则返回一个空串;如果请求消息中包含有多个该指定名称的参数,getParameter()方法返回第一个出现的参数值
String[] getParameterValues(String name) 该方法用于返回一个String类型的数组,HTTP请求消息中可以有多个相同名称的参数(通常由一个包含有多个同名的字段元素的form表单生成),如果要获得HTTP请求消息中的同一个参数名所对应的所有参数值,那么就应该使用getParameterValues()方法
Enumeration getParameterNames() 该方法用于返回一个包含请求消息中所有参数名的Enumeration对象,在此基础上,可以对请求消息中的所有参数进行遍历处理
Map getParameterMap() 该方法用于将请求消息中的所有参数名和值装入进一个Map对象中返回
2、案例演示
创建注册页面 - register.html

在net.huawei.request包里创建RquestParamsServlet类,用于获取注册表单提交的数据

对应关系图

重启tomcat服务器,访问http://localhost:8080/WebDemo/register.html,填写表单数据

单击【注册】按钮

(五)解决请求参数中文乱码问题
目标:掌握如何解决请求参数的中文乱码

在HttpServletRequest接口中,提供了一个setCharacterEncoding()方法,该方法用于设置request对象的解码方式

修改ResquestParamsServlet类,添加一行代码,设置请求对象的字符编码

重启tomcat服务器,访问http://localhost:8080/WebDemo/register.html,填写表单数据

单击【注册】按钮,页面没有中文乱码

录屏演示注册操作

(六)通过Request对象传递数据
目标:掌握使用ServletRequest接口操作属性
1、Request对象操作属性的方法
(1)setAttribute()方法
setAttribute()方法用于将一个对象与一个name关联后存储进ServletRequest对象中,其完整声明:public void setAttribute(String name,Object o);
setAttribute()方法的参数列表的第一个参数接收的是一个String类型的name,第二个参数接收的是一个Object类型的对象o。需要注意的是,如果ServletRequest对象中已经存在指定名称的属性,setAttribute()方法将会先删除原来的属性,然后再添加新的属性。如果传递给setAttribute()方法的属性值对象为null,则删除指定名称的属性,这时的效果等同于removeAttribute()方法。
(2)getAttribute()方法
getAttribute()方法用于从ServletRequest对象中返回指定名称的属性对象,其完整声明:public Object getAttribute(String name);
(3)removeAttribute()方法
removeAttribute()方法用于从ServletRequest对象中删除指定名称的属性,其完整声明:public void removeAttribute(String name);
(4)getAttributeNames()方法
getAttributeNames()方法用于返回一个包含ServletRequest对象中的所有属性名的Enumeration对象,在此基础上,可以对ServletRequest对象中的所有属性进行遍历处理。其完整声明:public Enumeration getAttributeNames();
需要注意,只有属于同一个请求中的数据才可以通过ServletRequest对象传递数据。
2、案例演示通过Request对象传递数据
在net.huawei.request包里创建RquestServlet01类

在net.huawei.request包里创建RquestServlet02类

启动服务器,访问http://localhost:8080/WebDemo/request01

修改RequestServlet02,只显示学生信息

启动服务器,访问http://localhost:8080/WebDemo/request01