文章目录
一、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接口的方法
方法声明 | 功能描述 |
---|---|
void init(ServletConfig config) | Servlet实例化后,Servlet容器调用该方法完成初始化工作 |
ServletConfig getServletConfig() | 用于获取Servlet对象的配置信息,返回Servlet的ServletConfig对象 |
String getServletInfo() | 返回一个字符串,其中包含关于Servlet的信息,例如,作者、版本和版权等信息 |
void service(ServletRequest request,ServletResponse response) | 负责响应用户的请求,当容器接收到客户端访问Servlet对象的请求时,就会调用此方法。容器会构造一个表示客户端请求信息的ServletRequest对象和一个用于响应客户端的ServletResponse对象作为参数传递给service()方法。在service()方法中,可以通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息 |
void destroy() | 负责释放Servlet对象占用的资源。当服务器关闭或者Servlet对象被移除时,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类的常用方法及功能
方法声明 | 功能描述 |
---|---|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) | 用于处理GET类型的Http请求的方法 |
protected void doPost(HttpServletRequest req, HttpServletResponse resp) | 用于处理POST类型的Http请求的方法 |
protected void doPut(HttpServletRequest req, HttpServletResponse resp) | 用于处理PUT类型的Http请求的方法 |
二、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.xyx.servlet包
-
在net.xyxi.servlet包里创建
ServletDemo01
类 -
此时IDEA工具会自动生成Servlet代码
-
为了更好地演示Servlet的运行效果,接下来在ServletDemo01的doGet()和doPost()方法中添加一些代码。在@WebServlet注解里设置urlPatterns属性值:urlPatterns = “/demo01”
package net.xyx.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;
/**
* 功能:Servlet演示类
* 作者:xyx
* 日期:2023年03月12日
*/
@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.xyx.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;
/**
* 功能:显示个人信息
* 作者:xyx
* 日期:2023年03月31日
*/
@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
-
无论浏览器当前采用什么字符编码,通过设置响应对象内容类型来要求浏览器采用指定的字符编码
-
重启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-name> | String 指定该Servlet的名称,一般与Servlet类名相同,要求唯一 |
<servlet-class> | String 指定该Servlet类的位置,包括包名与类名 |
<description> | String 指定该Servlet的描述信息 |
<display-name> | String 指定该Servlet的显示名 |
-
把Servlet映射到URL地址,使用标签进行映射,使用子标签指定要映射的Servlet名称,名称要和之前在标签下注册的相同;使用子标签映射URL地址,地址前必须加“/”,否则访问不到。
-
在部署描述文件web.xml里注册了Servlet,那么就可以注释掉InfoServlet类上的注解
-
重启tomcat服务器,访问
http://localhost:8080/ShowInfo/info
2、@WebServlet注解属性
- @WebServlet 注解用于代替web.xml文件中的等标签,该注解将会在项目部署时被容器处理,容器将根据具体的属性配置将相应的类部署为Servlet。为此,@WebServlet注解提供了一些属性。
属性声明 | 功能描述 |
---|---|
String name | 指定Servlet的name属性,等价于。如果没有显式指定,则该 |
Servlet的取值即为类的全限定名。 | |
String[] value | 该属性等价于urlPatterns属性。urlPatterns和value属性不能同时使用。 |
String[] urlPatterns | 指定一组Servlet的URL匹配模式。等价于标签。 |
int loadOnStartup | 指定Servlet的加载顺序,等价于标签。 |
WebInitParam[] | 指定一组Servlet初始化参数,等价于标签。 |
boolean asyncSupported | 声明Servlet是否支持异步操作模式,等价于 标签。 |
String description | Servlet的描述信息,等价于标签。 |
String displayName ervlet | 的显示名,通常配合工具使用,等价于 标签。 |
@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.xyx.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;
/**
* 功能:演示Servlet生命周期
* 作者:xyx
* 日期:2023年03月12日
*/
@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定义了一系列获取配置信息的方法。
方法说明 | 功能描述 |
---|---|
String getInitParameter(String name) | 根据初始化参数名返回对应的初始化参数值 |
Enumeration getInitParameterNames() | 返回一个Enumeration对象,其中包含了所有的初始化参数名 |
ServletContext getServletContext() | 返回一个代表当前Web应用的ServletContext对象 |
String getServletName() | 返回Servlet的名字 |
2、案例演示ServletConfig方法调用
- 以getInitParameter()方法为例讲解ServletConfig方法的调用
- 在WebDemo项目的net.huawei.servlet包里创建ServletDemo03类
package net.xyx.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;
/**
* 功能:演示ServletConfig方法的调用
* 作者:xyx
* 日期:2023年03月31日
*/
@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应用初始化参数的配置方式具体如下所示。
参数名
参数值
参数名
参数值
1
2
3
4
5
6
7
8
<context-param>
元素位于根元素<web-app>
中,它的子元素<param-name>
和<param-value>
分别用来指定参数的名字和参数值。可以通过调用ServletContext接口中定义- getInitParameterNames()和getInitParameter(String name)方法,分别获取参数名和参数值。
2、案例演示获取Web应用的容器初始化参数
- 在WebDemo项目的web.xml文件中,配置容器初始化参数信息和Servlet信息
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>college</param-name>
<param-value>泸州职业技术学院</param-value>
</context-param>
<context-param>
<param-name>address</param-name>
<param-value>泸州市龙马潭区长桥路2号</param-value>
</context-param>
<context-param>
<param-name>secretary</param-name>
<param-value>何杰</param-value>
</context-param>
<context-param>
<param-name>president</param-name>
<param-value>谢鸿全</param-value>
</context-param>
</web-app>
- 在net.huawei.servlet包里创建
ServletDemo04
类
package net.xyx.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应用的容器初始化参数
* 作者:xyx
* 日期: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域属性的四个方法。
方法说明 | 功能描述 |
---|---|
Enumeration getAttributeNames() | 返回一个Enumeration对象,该对象包含了所有存放在ServletContext中的所有域属性名 |
Object getAttibute(String name) | 根据参数指定的属性名返回一个与之匹配的域属性值 |
void removeAttribute(String name) | 根据参数指定的域属性名,从ServletContext中删除匹配的域属性 |
void setAttribute(String name,Object obj) | 设置ServletContext的域属性,其中name是域属性名,obj是域属性值 |
4、案例演示多个Servlet对象共享数据
- 在net.xyx.servlet包里创建
ServletDemo05
类
package net.xyx.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;
/**
* 功能:写入域属性
* 作者:xyx
* 日期: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.xyx.servlet包里创建
ServletDemo06
类
package net.xyxx.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;
/**
* 功能:读取域属性
* 作者:xyx
* 日期:2023年03月31日
*/
@WebServlet(name = "ServletDemo06", urlPatterns = "/demo06")
public class ServletDemo06 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> attributeNames = context.getAttributeNames();
// 通过循环显示域属性名与域属性值
while (attributeNames.hasMoreElements()) {
// 获取域属性名
String name = attributeNames.nextElement();
// 获取域属性值
Object value = context.getAttribute(name);
// 输出域属性名与域属性值
out.print(name + " : " + value + "<br />");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
启动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流、资源文件在文件系统的绝对路径等。
方法说明 | 功能描述 |
---|---|
Set getResourcePaths(String path) | 返回一个Set集合,集合中包含资源目录中子目录和文件的路径名称。参数path必须以正斜线(/)开始,指定匹配资源的部分路径 |
String getRealPath(String path) | 返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)。参数path代表资源文件的虚拟路径,它应该以正斜线(/)开始,“/”表示当前Web应用的根目录,如果Servlet容器不能将虚拟路径转换为文件系统的真实路径,则返回null |
URL getResource(String path) | 返回映射到某个资源文件的URL对象。参数path必须以正斜线(/)开始,“/”表示当前Web应用的根目录 |
InputStream getResourceAsStream(String path) | 返回映射到某个资源文件的InputStream输入流对象。参数path传递规则和getResource()方法完全一致 |
6、案例演示读取Web应用下的资源文件
- 在net.xyx.servlet包里创建属性文件 -
college.properties
name = 泸州职业技术学院
address = 泸州市龙马潭区长桥路2号
secretary = 何杰
president = 谢鸿全
- 在net.xyxservlet包里创建
ServletDemo07
类
package net.xyx.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.InputStream;
import java.io.PrintWriter;
import java.util.Properties;
/**
* 功能:读取资源文件
* 作者:xyx
* 日期:2023年03月13日
*/
@WebServlet(name = "ServletDemo07", urlPatterns = "/demo07")
public class ServletDemo07 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置内容类型
response.setContentType("text/html; charset=utf-8");
// 获取Servlet容器对象
ServletContext context = getServletContext();
// 获取打印输出流
PrintWriter out = response.getWriter();
// 读取资源文件,得到字节输入流
InputStream in = context.getResourceAsStream(
"/WEB-INF/classes/net/huawei/servlet/college.properties");
// 创建属性对象(Map接口的实现类)
Properties pros = new Properties();
// 属性对象加载资源文件的资源文件输入流
pros.load(in);
// 往客户端输出属性值
out.println("name = " + pros.getProperty("name") + "<br />");
out.println("address = " + pros.getProperty("address") + "<br />");
out.println("secretary = " + pros.getProperty("secretary") + "<br />");
out.println("president = " + pros.getProperty("president") + "<br />");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
启动tomcat服务器,访问
http://localhost:8080/WebDemo/demo07
-
属性文件的路径问题
-
读取属性文件得到的字节流编码是ISO-8859-1,需要做一个转码处理
-
重启tomcat服务器,先访问
http://localhost:8080/WebDemo/demo07
-
在Web项目开发中开发者可能需要获取资源的绝对路径。通过调用getRealPath(String path)方法获取资源文件的绝对路径。
-
在net.xyx.servlet包里创建ServletDemo08类
package net.xyx.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;
/**
* 功能:获取资源的绝对路径
* 作者:xyx
* 日期:2023年03月13日
*/
@WebServlet(name = "ServletDemo08", urlPatterns = "/demo08")
public class ServletDemo08 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取Servlet容器对象
ServletContext context = getServletContext();
// 获取打印输出流
PrintWriter out = response.getWriter();
// 创建资源路径字符串
String path = "/WEB-INF/classes/net/huawei/servlet/college.properties";
// 获取资源绝对路径
String realPath = context.getRealPath(path);
// 输出资源绝对路径
out.println("college.properties: " + realPath);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
- 重启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响应头字段的方法
方法说明 | 功能描述 |
---|---|
void addHeader(String name, String value) | 用来设置HTTP协议的响应头字段,其中,参数name用于指定响应头字段的名称,参数value用于指定响应头字段的值。addHeader()方法可以增加同名的响应头字段 |
void setHeader(String name, String value) | 用来设置HTTP协议的响应头字段,其中,参数name用于指定响应头字段的名称,参数value用于指定响应头字段的值。setHeader()方法则会覆盖同名的头字段 |
void addIntHeader(String name, int value) | 专门用于设置包含整数值的响应头。避免了调用addHeader()方法时,需要将int类型的设置值转换为String类型的麻烦 |
void setIntHeader(String name, int value) | 专门用于设置包含整数值的响应头。避免了调用setHeader()方法时,需要将int类型的设置值转换为String类型的麻烦 |
void setContentLength(int len) | 该方法用于设置响应消息的实体内容的大小,单位为字节。对于HTTP协议来说,这个方法就是设置Content-Length响应头字段的值 |
void setContentType(String type) | 该方法用于设置Servlet输出内容的MIME类型,对于HTTP协议来说,就是设置Content-Type响应头字段的值。例如,如果发送到客户端的内容是jpeg格式的图像数据,就需要将响应头字段的类型设置为“image/jpeg”。需要注意的是,如果响应的内容为文本,setContentType()方法的还可以设置字符编码,如:text/html;charset=UTF-8 |
void setLocale(Locale loc) | 该方法用于设置响应消息的本地化信息。对HTTP来说,就是设置Content-Language响应头字段和Content-Type头字段中的字符集编码部分。需要注意的是,如果HTTP消息没有设置Content-Type头字段,setLocale()方法设置的字符集编码不会出现在HTTP消息的响应头中,如果调用setCharacterEncoding()或setContentType()方法指定了响应内容的字符集编码,setLocale()方法将不再具有指定字符集编码的功能 |
void setCharacterEncoding(String charset) | 该方法用于设置输出内容使用的字符编码,对HTTP 协议来说,就是设置Content-Type头字段中的字符集编码部分。如果没有设置Content-Type头字段,setCharacterEncoding方法设置的字符集编码不会出现在HTTP消息的响应头中。setCharacterEncoding()方法比setContentType()和setLocale()方法的优先权高,setCharacterEncoding()方法的设置结果将覆盖setContentType()和setLocale()方法所设置的字符码表 |
- 需要注意的是,addHeader()、setHeader()、addIntHeader()、setIntHeader()方法都是用于设置各种头字段的,而setContetType()、setLoacale()和setCharacterEncoding()方法用于设置字符编码,这些设置字符编码的方法可以有效解决中文字符乱码问题。
(三)发送响应消息体相关的方法
- 目标:掌握发送响应消息体相关的方法getOutputStream()和getWriter()
- 由于在HTTP响应消息中,大量的数据都是通过响应消息体传递的,所以,ServletResponse遵循IO流传递大量数据的设计理念。在发送响应消息体时,定义了两个与输出流相关的方法。
1、getOutputStream()方法
- getOutputStream()方法所获取的字节输出流对象为ServletOutputStream类型。由于ServletOutputStream是OutputStream的子类,它可以直接输出字节数组中的二进制数据。所以,要想输出二进制格式的响应正文,就需要调用getOutputStream()方法。
2、getWriter()方法
getWriter()方法所获取的字符输出流对象为PrintWriter类型。由于PrintWriter类型的对象可以直接输出字符文本内容,所以,要想输出内容为字符文本的网页文档,需要调用getWriter()方法。
3、案例演示发送响应消息体
-
创建net.xyx.response包
-
在net.xyx.response包里创建PrintServlet01类
package net.huawei.response;
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.OutputStream;
/**
* 功能:演示响应体输出字节流
* 作者:xyx
* 日期:2023年04月07日
*/
@WebServlet(name = "PrintServlet01", urlPatterns = "/print01")
public class PrintServlet01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 定义字符串数据
String data = "欢迎访问泸州职业技术学院~";
// 获取字节输出流对象
OutputStream out = response.getOutputStream();
// 往客户端输出信息
out.write(data.getBytes());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
重启tomcat服务器,访问
http://localhost:8080/WebDemo/print01
-
在net.xyx.response包里创建
PrintServlet02
类
package net.xyx.response;
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;
/**
* 功能:演示响应体打印字符流
* 作者:xyx
* 日期:2023年04月07日
*/
@WebServlet(name = "PrintServlet02", urlPatterns = "/print02")
public class PrintServlet02 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 定义字符串数据
String data = "欢迎访问泸州职业技术学院~";
// 获取打印字符流
PrintWriter out = response.getWriter();
// 往客户端输出信息
out.println(data);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
重启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
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="login" method="post">
<fieldset>
<legend>用户登录</legend>
<table cellpadding="2" align="center">
<tr>
<td align="right">用户名:</td>
<td>
<input type="text" name="username"/>
</td>
</tr>
<tr>
<td align="right">密码:</td>
<td>
<input type="password" name="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="登录"/>
<input type="reset" value="重置"/>
</td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>
- 创建欢迎页面 -
welcome.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功</title>
</head>
<body>
<h3 style="text-align: center">欢迎你,登录成功~</h3>
</body>
</html>
- 在net.xyx.response包里创建LoginServlet类,处理用户登录请求
package net.xyx.response;
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;
/**
* 功能:登录处理程序
* 作者:xyx
* 日期:2023年04月07日
*/
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 获取登录表单提交的用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 判断是否登录成功,决定重定向到不同页面
if ("howard".equals(username) && "903213".equals(password)) {
// 重定向到欢迎页面
response.sendRedirect("/WebDemo/welcome.html");
} else {
// 重定向到登录页面
response.sendRedirect("/WebDemo/login.html");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
重启tomcat服务器,访问
http://localhost:8080/WebDemo/login.html
-
在login.html页面填写用户名“howard”,密码“903213”
-
单击登录按钮,跳转到欢迎页面
-
录屏操作演示
(二)动手实践:解决中文输出乱码问题
- 目标:掌握如何解决中文输出乱码问题
1、中文乱码问题
- 由于计算机中的数据都是以二进制形式存储的,所以,当传输文本时,就会发生字符和字节之间的转换。字符与字节之间的转换是通过查码表完成的,将字符转换成字节的过程称为编码,将字节转换成字符的过程称为解码,如果编码和解码使用的码表不一致,就会导致乱码问题。
2、案例演示解决乱码问题
在net.xyx.response包里创建ChineseServlet
类
package net.xyx.response;
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;
/**
* 功能:演示解决中文乱码问题
* 作者:xyx
* 日期:2023年03月13日
*/
@WebServlet(name = "ChineseServlet", urlPatterns = "/chinese")
public class ChineseServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 创建数据字符串
String data = "欢迎访问泸州职业技术学院~";
// 获取打印字符输出流
PrintWriter out = response.getWriter();
// 在页面输出信息
out.println(data);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}```
- 重启tomcat服务器,访问`http://localhost:8080/WebDemo/chinese`
![在这里插入图片描述](https://img-blog.csdnimg.cn/3753008021754cc7920353c6cc2bf59c.png)
- 浏览器显示的内容都是“???~”,说明发生了乱码问题。此处产生乱码的原因是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。
![在这里插入图片描述](https://img-blog.csdnimg.cn/32a6839c1db04258ab530e61cfaf0016.png)
- 重启tomcat服务器,访问`http://localhost:8080/WebDemo/chinese`
![在这里插入图片描述](https://img-blog.csdnimg.cn/48e9a1a0e1f546668a6d10a43571a91e.png)
- 浏览器中显示的乱码虽然不是`“????????????~`”,但也不是需要输出的“欢迎访问泸州职业技术学院~”,这是由于浏览器解码错误导致的。`response`对象的字符输出流设置的编码方式为UTF-8,而浏览器使用的解码方式是GBK。
![在这里插入图片描述](https://img-blog.csdnimg.cn/add083a55c9e4b7aa610a2d40b99db2d.png)
- 将`response`对象的字符输出流设置的编码方式改为GBK
![在这里插入图片描述](https://img-blog.csdnimg.cn/840004418f7445d8aa98e20b05f76f9d.png)
- 重启tomcat服务器,访问`http://localhost:8080/WebDemo/chinese`
![在这里插入图片描述](https://img-blog.csdnimg.cn/4e1e71fe15cf45478753ea9452820329.png)
- 一种更好的方法来解决页面中文乱码问题,直接要求浏览器按照某种字符编码来显示中文
![在这里插入图片描述](https://img-blog.csdnimg.cn/14e0758fdc5845a9b6e78c6496bbeeb0.png)
`response.setContentType("text/html;charset=utf-8")`;让浏览器采用utf-8字符编码
- 重启tomcat服务器,访问`http://localhost:8080/WebDemo/chinese`
![在这里插入图片描述](https://img-blog.csdnimg.cn/444bdde3831445ea904f78df7f79a7e0.png)
- 当然也可以换种方式来解决
```xml
// 设置HttpServletResponse使用utf-8编码
response.setCharacterEncoding("utf-8");
// 通知浏览器使用utf-8解码
response.setHeader("Content-Type", "text/html;charset=utf-8");
六、HttpServletRequest对象
(一)获取请求行信息的相关方法
- 目标:掌握使用
HttpServletRequest
接口中的方法获取请求行
1、相关方法
方法声明 | 功能描述 |
---|---|
String getMethod( ) | 该方法用于获取HTTP请求消息中的请求方式(如GET、POST等) |
String getRequestURI( ) | 该方法用于获取请求行中资源名称部分,即位于URL的主机和端口之后、参数部分之前的数据 |
String getQueryString( ) | 该方法用于获取请求行中的参数部分,也就是资源路径后面问号(?)以后的所有内容 |
String getProtocol( ) | 该方法用于获取请求行中的协议名和版本,例如HTTP/1.0或HTTP/1.1 |
String getContextPath( ) | 该方法用于获取请求URL中属于Web应用程序的路径,这个路径以“/”开头,表示相对于整个Web站点的根目录,路径结尾不含“/”。如果请求URL属于Web站点的根目录,那么返回结果为空字符串(“”) |
String getServletPath( ) | 该方法用于获取Servlet的名称或Servlet所映射的路径 |
String getRemoteAddr( ) | 该方法用于获取请求客户端的IP地址,其格式类似于“192.168.0.3” |
String getRemoteHost( ) | 该方法用于获取请求客户端的完整主机名,其格式类似于“pc1.itcast.cn”。需要注意的是,如果无法解析出客户机的完整主机名,该方法将会返回客户端的IP地址 |
int getRemotePort() | 该方法用于获取请求客户端网络连接的端口号 |
String getLocalAddr() | 该方法用于获取Web服务器上接收当前请求网络连接的IP地址 |
String getLocalName() | 该方法用于获取Web服务器上接收当前网络连接IP所对应的主机名 |
int getLocalPort() | 该方法用于获取Web服务器上接收当前网络连接的端口号 |
String getServerName() | 该方法用于获取当前请求所指向的主机名,即HTTP请求消息中Host头字段所对应的主机名部分 |
int getServerPort() | 该方法用于获取当前请求所连接的服务器端口号,即如果HTTP请求消息中Host头字段所对应的端口号部分 |
String getScheme() | 该方法用于获取请求的协议名,例如http、https或ftp |
StringBuffer getRequestURL() | 该方法用于获取客户端发出请求时的完整URL,包括协议、服务器名、端口号、资源路径等信息,但不包括后面的查询参数部分。注意,getRequestURL()方法返回的结果是StringBuffer类型,而不是String类型,这样更便于对结果进行修改 |
2、案例演示
创建net.xyx.request包,在包里创建RequestLineServlet
类
package net.xyx.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;
/**
* 功能:输出请求行的相关信息
* 作者:xyx
* 日期:2023年03月13日
*/
@WebServlet(name = "RequestLineServlet", urlPatterns = "/request")
public class RequestLineServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html;charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 获取并输出请求行的相关信息
out.println("getMethod: " + request.getMethod() + "<br />");
out.println("getRequestURI: " + request.getRequestURI() + "<br />");
out.println("getQueryString: " + request.getQueryString() + "<br />");
out.println("getProtocol: " + request.getProtocol() + "<br />");
out.println("getContextPath: " + request.getContextPath() + "<br />");
out.println("getPathInfo: " + request.getPathInfo() + "<br />");
out.println("getPathTranslated: " + request.getPathTranslated() + "<br />");
out.println("getServletPath: " + request.getServletPath() + "<br />");
out.println("getRemoteAddr: " + request.getRemoteAddr() + "<br />");
out.println("getRemoteHost: " + request.getRemoteHost() + "<br />");
out.println("getRemotePort: " + request.getRemotePort() + "<br />");
out.println("getLocalAddr: " + request.getLocalAddr() + "<br />");
out.println("getLocalName: " + request.getLocalName() + "<br />");
out.println("getLocalPort: " + request.getLocalPort() + "<br />");
out.println("getServerName: " + request.getServerName() + "<br />");
out.println("getServerPort: " + request.getServerPort() + "<br />");
out.println("getScheme: " + request.getScheme() + "<br />");
out.println("getRequestURL: " + request.getRequestURL() + "<br />");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
重启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 统一资源定位器
演示请求字符串
package net.xyx.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;
/**
* 功能:输出请求行的相关信息
* 作者:xyx
* 日期:2023年04月14日
*/
@WebServlet(name = "RequestLineServlet", urlPatterns = "/request")
public class RequestLineServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 获取并输出请求行的相关信息
out.println("getMethod: " + request.getMethod() + "<br />");
out.println("getRequestURI: " + request.getRequestURI() + "<br />");
out.println("getQueryString: " + request.getQueryString() + "<br />");
out.println("getProtocol: " + request.getProtocol() + "<br />");
out.println("getContextPath: " + request.getContextPath() + "<br />");
out.println("getPathInfo: " + request.getPathInfo() + "<br />");
out.println("getPathTranslated: " + request.getPathTranslated() + "<br />");
out.println("getServletPath: " + request.getServletPath() + "<br />");
out.println("getRemoteAddr: " + request.getRemoteAddr() + "<br />");
out.println("getRemoteHost: " + request.getRemoteHost() + "<br />");
out.println("getRemotePort: " + request.getRemotePort() + "<br />");
out.println("getLocalAddr: " + request.getLocalAddr() + "<br />");
out.println("getLocalName: " + request.getLocalName() + "<br />");
out.println("getLocalPort: " + request.getLocalPort() + "<br />");
out.println("getServerName: " + request.getServerName() + "<br />");
out.println("getServerPort: " + request.getServerPort() + "<br />");
out.println("getScheme: " + request.getScheme() + "<br />");
out.println("getRequestURL: " + request.getRequestURL() + "<br />");
// 在控制台输出请求字符串的信息
if (request.getQueryString() != null) {
String strQuery = request.getQueryString();
String[] queries = strQuery.split("&");
for (String query : queries) {
String[] fields = query.split("=");
System.out.println(fields[0] + " : " + fields[1]);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
- 重启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() | |
String getCharacterEncoding() | 该方法用于返回请求消息的实体部分的字符集编码,通常是从Content-Type头字段中进行提取,结果为String类型 |
2、案例演示
- 在net.xyx.request包里创建
RequestHeadersServlet
类
package net.xyx.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;
/**
* 功能:演示获取请求头的信息
* 作者:xyx
* 日期: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<String> headerNames = request.getHeaderNames();
// 遍历所有请求头,并通过getHeader()方法获取一个指定名称的头字段
while (headerNames.hasMoreElements()) {
// 获取头字段名称
String headerName = headerNames.nextElement();
// 输出头字段名称及其值
out.println(headerName + " : " + request.getHeader(headerName) + "<br />");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
重启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.xyx.request包里创建RequestForwardServlet
类,将数据保存在request
对象里,然后转发给另一个Servlet
来处理
package net.xyx.request;
import javax.servlet.RequestDispatcher;
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;
/**
* 功能:演示请求转发
* 作者:xyx
* 日期:2023年03月13日
*/
@WebServlet(name = "RequestForwardServlet", urlPatterns = "/forward")
public class RequestForwardServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html;charset=utf-8");
// 设置请求对象属性
request.setAttribute("message", "欢迎访问泸州职业技术学院~");
// 获取请求派发器对象(参数是请求转发的Servlet的url)
RequestDispatcher dispatcher = request.getRequestDispatcher("/result");
// 请求转发给url为`/result`的Servlet
dispatcher.forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
在net.xyx.request包里创建ResultServlet
类,用于获取RequestForwardServlet
类中存储在request
对象中的数据并输出
package net.xyx.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;
/**
* 功能:处理转发的请求
* 作者:xyx
* 日期:2023年03月13日
*/
@WebServlet(name = "ResultServlet", urlPatterns = "/result")
public class ResultServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html;charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 获取请求转发保存在request对象里的数据
String message = (String) request.getAttribute("message");
// 输出获取的信息
if (message != null) {
out.println("转发来的消息:" + message);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
对应关系图
重启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
用户名: | |
密码: | |
性别: | 男 女 |
兴趣: | 看电影 敲代码 玩游戏 |
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
41
42
43
44
45
46
47
48
49
- 在net.xyx.request包里创建
RquestParamsServlet
类,用于获取注册表单提交的数据
package net.xyx.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;
/**
* 功能:获取请求参数
* 作者:XYX
* 日期:2023年04月14日
*/
@WebServlet(name = "RequestParamsServlet", urlPatterns = "/register")
public class RequestParamsServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 获取注册表单提交的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
String gender = request.getParameter("gender");
String[] interests = request.getParameterValues("interest");
// 输出获取的表单数据
out.println("姓名:" + username + "<br />");
out.println("密码:" + password + "<br />");
out.println("性别:" + gender + "<br />");
out.print("兴趣:");
for (int i = 0; i < interests.length; i++) {
out.println(interests[i]);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
对应关系图
重启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.xyx.request包里创建RquestServlet01
类
package net.xyx.request;
import javax.servlet.RequestDispatcher;
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;
/**
* 功能:设置请求对象属性,请求转发
* 作者:xyx
* 日期:2023年04月14日
*/
@WebServlet(name = "RequestServlet01", urlPatterns = "/request01")
public class RequestServlet01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 设置请求对象属性
request.setAttribute("id", "20210201");
request.setAttribute("name", "陈燕文");
request.setAttribute("gender", "女");
request.setAttribute("age", "18");
request.setAttribute("major", "软件技术专业");
request.setAttribute("class", "2021级软件2班");
request.setAttribute("phone", "15890903456");
// 获取请求派发器对象(参数是请求转发的Servlet的url)
RequestDispatcher dispatcher = request.getRequestDispatcher("/request02");
// 请求转发给url为`/request02`的Servlet
dispatcher.forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
- 在
net.xyx.request
包里创建RquestServlet02
类
package net.xyx.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;
/**
* 功能:获取请求转发的数据
* 作者:xyx
* 日期:2023年04月14日
*/
@WebServlet(name = "RequestServlet02", urlPatterns = "/request02")
public class RequestServlet02 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 获取请求对象属性名枚举对象
Enumeration<String> attributes = request.getAttributeNames();
// 获取请求转发保存在request对象里的数据并输出
while (attributes.hasMoreElements()) {
// 获取属性名
String attribute = attributes.nextElement();
// 输出属性名及其值
out.println(attribute + " : " + request.getAttribute(attribute) + "<br />");
}
// 删除请求对象的属性
while (attributes.hasMoreElements()) {
// 获取属性名
String attribute = attributes.nextElement();
// 删除属性
request.removeAttribute(attribute);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
-
启动服务器,访问
http://localhost:8080/WebDemo/request01
-
修改RequestServlet02,只显示学生信息
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;
/**
* 功能:获取请求转发的数据
* 作者:xyx
* 日期:2023年04月14日
*/
@WebServlet(name = "RequestServlet02", urlPatterns = "/request02")
public class RequestServlet02 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应体内容类型
response.setContentType("text/html; charset=utf-8");
// 获取字符输出流
PrintWriter out = response.getWriter();
// 获取请求转发保存在request对象里的数据并输出
out.println("学号:" + request.getAttribute("id") + "<br />");
out.println("姓名:" + request.getAttribute("name") + "<br />");
out.println("性别:" + request.getAttribute("gender") + "<br />");
out.println("年龄:" + request.getAttribute("age") + "<br />");
out.println("专业:" + request.getAttribute("major") + "<br />");
out.println("班级:" + request.getAttribute("class") + "<br />");
out.println("手机:" + request.getAttribute("phone") + "<br />");
// 删除请求对象的属性
request.removeAttribute("id");
request.removeAttribute("name");
request.removeAttribute("gender");
request.removeAttribute("age");
request.removeAttribute("major");
request.removeAttribute("class");
request.removeAttribute("phone");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
- 启动服务器,访问
http://localhost:8080/WebDemo/request01