一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
写在前面👀
今天主要讲讲Servlet的体系结构和HttpServletRequest接口获取客户端
请求信息的一些方法
一、Servlet体系结构
上回书说到,使用Servlet就必须要实现Servlet接口,重写接口中的5个方法,这是比较麻烦的,我们更关注的其实只有service方法,那有没有更简单方式来创建Servlet呢?
要想解决上面的问题,我们需要先对Servlet的体系结构进行下了解
1️⃣继承关系
a.Servlet根接口
- 从上图可以看出,Servlet接口的基本目标是提供与Servlet生命周期相关的方法,如:init()、service()和destroy()等
b.GenericServlet抽象类
- 继承自Servlet,除了重写了五个方法外,还多了其他方法。
- 不常用
c.HttpServlet类
- HttpServlet指能够处理HTTP请求的Servlet,它在原有Servlet接口上添加了对HTTP协议的处理,它比Servlet接口的功能更为强大,比前两个Servlet更常用
- HttpServlet在实现Servlet接口时,重写了service()方法,该方法会自动判断用户的请求方式
- 若为若为GET请求,则调用HttpServlet的
doGet( )方法;若为POST请求,则调用doPost( )方法。当然还有别的请求方式
- 若为若为GET请求,则调用HttpServlet的
2️⃣自定义HttpServlet类
HttpServlet类已经为我们封装好了和HTTP有关许多复杂的操作,而B/S架构的web项目,都是针对HTTP协议的。作为程序员,我们选择继承
HttpServlet类时,通常只需要重写**doGet( )或doPost( )**方法,来处理GET和POST请求,而不需要去重写service方法。
编写格式示例💥
@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//TODO GET 请求方式处理逻辑
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//TODO Post 请求方式处理逻辑
}
}
二、HttpServletRequest
1️⃣什么是HttpServletRequest?
在 Servlet API 中,定义了一个 HttpServletRequest 接口,它继承自 ServletRequest 接口。HttpServletRequest的实现类RequestFacade对象专门用于封装 HTTP 请求消息,简称 request 对象。
2️⃣HttpServletRequest继承体系
我们都知道,HttpServletRequest是一个接口,而接口是不能直接创建对象的,所以tomcat就定义了一个HttpServletRequest接口的实现类——RequestFacade,而这个类的对象也是由tomcat创建的。
验证猜想
- 编写一个Servlet,把request对象打印下,可以看到,他的类型确实为
RequestFacade
/**
* 验证request的类型
*/
@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(request);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
- 演示结果如下👇
3️⃣RequestFacade的API
-
要想了解RequestFacade中都提供了哪些方法,我们可以直接查看JavaEE的API文档中关于ServletRequest和HttpServletRequest的接口文档,因为RequestFacade实现了其接口就需要重写接口中的方法
三、Request获取请求数据
HTTP请求数据总共分为三部分内容,分别是请求行、请求头、请求体,下面通过几个实例来演示下如何获取这些请求数据
1️⃣获取请求行数据
请求行包含三块内容,分别是
请求方式、请求资源路径、HTTP协议及版本
a.接口方法
- HttpServletRequest 接口定义了一系列获取请求行信息的方法,如下表
| 返回值类型 | 方法声明 | 描述 |
|---|---|---|
| String | getMethod() | 获取 HTTP 请求方式(如 GET、POST 等)。 |
| String | getContextPath() | 获取虚拟目录(项目访问路径),如/tomcat |
| String | getServletPath() | 获取 Servlet 所映射的路径,如/req1 |
| String | getRequestURI() | 获取URI(统一资源标识符),即位于 URL 的主机和端口之后,参数部分之前的部分,如/tomcat/req1 |
| StringBuffer | getRequestURL() | 获取URL(统一资源定位符),如http://localhost:8080/tomcat/req1 |
| String | getQueryString() | 获取请求行的参数(GET方式),也就是 URL 中“?”以后的所有内容,如username=bighorn&&password=123456 |
| String | getRemoteAddr() | 获取客户端的 IP 地址。 |
| String | getRemoteHost() | 获取客户端的完整主机名,如果无法解析出客户机的完整主机名,则该方法将会返回客户端的 IP 地址。 |
b.代码示例
下面以获取GET请求行数据为例。
- 创建一个HttpServlet的子类:
RequestDemo1,Servlet映射路径:/req1
/**
* request 获取请求行数据
*/
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.获取请求方式: GET
String method = req.getMethod();
System.out.println("请求方式:" + method);
// 2.获取虚拟目录(项目访问路径):/tomcat
String contextPath = req.getContextPath();
System.out.println("项目访问路径:" + contextPath);
// 3.获取Servlet映射路径:/req1
String servletPath = req.getServletPath();
System.out.println("Servlet映射路径:" + servletPath);
// 4.获取URI(统一资源标识符):/tomcat/req1
String uri = req.getRequestURI();
System.out.println("URI:" + uri);
// 5.获取URL(统一资源定位符):http://localhost:8080/tomcat/req1
StringBuffer url = req.getRequestURL();
System.out.println("URL:" + url.toString());
// 6.获取请求参数(GET方式): username=bighorn&&password=123456
String queryString = req.getQueryString();
System.out.println("请求参数:" + queryString);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
-
启动tomcat服务器
-
在浏览器地址栏输入,敲回车
localhost:8080/tomcat/req1?username=bighorn&&password=123456
c.演示结果
2️⃣获取请求头数据
当浏览器发送请求时,需要通过请求头向服务器传递一些附加信息,例如客户端可以接收的数据类型、压缩方式、语言等
- 请求头的数据,是
键值对的形式,例如下图👇
a.接口方法
- HttpServletRequest 接口定义了一系列获取请求头信息的方法,如下表
| 返回值类型 | 方法声明 | 描述 |
|---|---|---|
| String | getHeader(String name) | 获取一个指定头字段的值。 如果请求消息中包含多个指定名称的头字段,则该方法返回其中第一个头字段的值。 |
| Enumeration | getHeaders(String name) | 返回指定头字段的所有值的枚举集合, 在多数情况下,一个头字段名在请求消息中只出现一次,但有时可能会出现多次。 |
| Enumeration | getHeaderNames() | 返回请求头中所有头字段的枚举集合。 |
| String | getContentType() | 获取 Content-Type 头字段的值。 |
| int | getContentLength() | 获取 Content-Length 头字段的值 。 |
| String | getCharacterEncoding() | 返回请求消息的字符集编码 。 |
b.代码示例
下面以获取GET请求头数据为例。
- 创建一个HttpServlet的子类:
RequestDemo2,Servlet映射路径:/req2
/**
* request 获取请求头数据
*/
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得所有请求头字段的枚举集合
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
//获得请求头字段的key,即字段名
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
//获得请求头字段的val,即字段值
System.out.println(headerName + ":" + headerValue);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
-
启动tomcat服务器
-
在浏览器地址栏输入,敲回车
localhost:8080/tomcat/req2
c.演示结果
3️⃣ 获取请求体数据
众所周知,GET请求的时候是没有请求体的,所以需要把请求方式变更为
POST,请求体里大多是客户端传入的参数。
- 请求体中的数据格式如下👇
a.接口方法
- HttpServletRequest 接口定义了一系列获取请求头信息的方法,如下表
| 返回值类型 | 方法声明 | 描述 |
|---|---|---|
| ServletInputStream | getInputStream() | 获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法 |
| BufferedReader | getReader() | 获取字符输入流,如果前端发送的是纯文本数据,则使用该方法 |
b.代码示例
下面以获取POST请求体纯文本数据为例。
webapp目录下添加一个html文件,名称为:login.html。添加一个表单类型标签,设置请求方式为POST,请求路径为/tomcat/req3。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/tomcat/req3" method="post">
账号:<input type="text" name="username">
<br>
密码:<input type="password" name="password">
<br>
<input type="submit" value="登录">
</form>
</body>
</html>
- 创建一个HttpServlet的子类:
RequestDemo3,Servlet映射路径:/req3
/**
* 获取请求体数据(POST请求方式)
*/
@WebServlet("/req3")
public class RequestDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.获取请求方式: POST
String method = request.getMethod();
System.out.println("请求方式:" + method);
// 2. 获取字符输入流
BufferedReader br = request.getReader();
// 3. 读取数据
String line = br.readLine();
System.out.println("请求体数据:"+line);
}
}
-
启动tomcat服务器
-
在浏览器地址栏输入,敲回车
localhost:8080/tomcat/login.html
- 在表单输入账号和密码
c.演示结果
写在后面🍻
感谢观看啦✨
有什么不足,欢迎指出哦💖
掘金的运营同学审核辛苦了💗