HttpServletRequest接口详解
一般情况下,浏览器(客户端)通过 HTTP 协议来访问服务器的资源,Servlet 主要用来处理 HTTP 请求。
Servlet 处理 HTTP 请求的流程如下:
通过以上流程可以看出, HttpServletRequest 和 HttpServletReponse 是 Servlet 处理 HTTP 请求流程中最重要的两个对象。HttpServletRequest 对象用于封装 HTTP 请求信息,HttpServletReponse 对象用于封装 HTTP 响应信息。
下面我们将对 HttpServletRequest 进行详细介绍。
HTTP 请求消息分为请求行、请求消息头和请求消息体三部分,所以 HttpServletRequest 接口中定义了获取请求行、请求头和请求消息体的相关方法。
创建一个名称为 httpServletRequestDemo 的项目,在 net.biancheng.www 包中创建一个名为 RequestLine 的 Servlet 类,代码如下。
启动 Tomcat 服务器,在地址栏中输入“http://localhost:8080/httpServletRequestDemo/RequestLine?a=1&b=2”,访问 RequestLine,结果如下图。
在 net.biancheng.www 包中创建一个名为 RequestHeader 的 Servlet 类,代码如下。
启动 Tomcat 服务器,在地址栏中输入“http://localhost:8080/httpServletRequestDemo/RequestHeader”,访问 RequestHeader ,结果如下图。
在 httpServletRequestDemo 的 WebContent 目录下,创建 form.html,代码如下。
在 net.biancheng.www 包中,创建一个名为 RequestParam 的 Servlet 类,代码如下。
启动 Tomcat 服务器,在地址栏中输入“http://localhost:8080/httpServletRequestDemo/form.html”,即可访问 form.html,结果如下图。
在表单中填写信息后,点击提交,结果如下图。
根据请求方式的不同,请求一般可以被分为两种:GET 请求和 POST 请求。这两种请求方式都可能会产生中文乱码问题,下面我们分别对它们产生乱码的原因及其解决方案进行介绍。
解决方案:在获取请求参数之前设置 request 缓冲区字符集为 utf-8 ,代码如下。
解决方案:解决 GET 请求中文乱码问题,有以下 3 种解决方案。
1. 修改 tomcat/conf/server.xml 中的配置,代码如下。
2. 使用 URLEncoder 和 URLDecoder 进行编码和解码的操作(逆向编解码)。
3. 使用 String 的构造方法:String(byte[] bytes, String charset) ,对字节数组(bytes)按照指定的字符集(charset)进行解码,返回解码后的字符串,解决乱码问题(推荐使用)。
Servlet 处理 HTTP 请求的流程如下:
![](https://img2022.cnblogs.com/blog/2589330/202208/2589330-20220830133748353-103250840.png)
- Servlet 容器接收到来自客户端的 HTTP 请求后,容器会针对该请求分别创建一个 HttpServletRequest 对象和 HttpServletReponse 对象。
- 容器将 HttpServletRequest 对象和 HttpServletReponse 对象以参数的形式传入 service() 方法内,并调用该方法。
- 在 service() 方法中 Servlet 通过 HttpServletRequest 对象获取客户端信息以及请求的相关信息。
- 对 HTTP 请求进行处理。
- 请求处理完成后,将响应信息封装到 HttpServletReponse 对象中。
- Servlet 容器将响应信息返回给客户端。
- 当 Servlet 容器将响应信息返回给客户端后,HttpServletRequest 对象和 HttpServletReponse 对象被销毁。
通过以上流程可以看出, HttpServletRequest 和 HttpServletReponse 是 Servlet 处理 HTTP 请求流程中最重要的两个对象。HttpServletRequest 对象用于封装 HTTP 请求信息,HttpServletReponse 对象用于封装 HTTP 响应信息。
下面我们将对 HttpServletRequest 进行详细介绍。
HttpServletRequest 接口
在 Servlet API 中,定义了一个 HttpServletRequest 接口,它继承自 ServletRequest 接口。HttpServletRequest 对象专门用于封装 HTTP 请求消息,简称 request 对象。HTTP 请求消息分为请求行、请求消息头和请求消息体三部分,所以 HttpServletRequest 接口中定义了获取请求行、请求头和请求消息体的相关方法。
获取请求行信息
HTTP 请求的请求行中包含请求方法、请求资源名、请求路径等信息,HttpServletRequest 接口定义了一系列获取请求行信息的方法,如下表。返回值类型 | 方法声明 | 描述 |
---|---|---|
String | getMethod() | 该方法用于获取 HTTP 请求方式(如 GET、POST 等)。 |
String | getRequestURI() | 该方法用于获取请求行中的资源名称部分,即位于 URL 的主机和端口之后,参数部分之前的部分。 |
String | getQueryString() | 该方法用于获取请求行中的参数部分,也就是 URL 中“?”以后的所有内容。 |
String | getContextPath() | 返回当前 Servlet 所在的应用的名字(上下文)。对于默认(ROOT)上下文中的 Servlet,此方法返回空字符串""。 |
String | getServletPath() | 该方法用于获取 Servlet 所映射的路径。 |
String | getRemoteAddr() | 该方法用于获取客户端的 IP 地址。 |
String | getRemoteHost() | 该方法用于获取客户端的完整主机名,如果无法解析出客户机的完整主机名,则该方法将会返回客户端的 IP 地址。 |
示例 1
为了更好地理解这些方法,下面通过案例演示这些方法的使用。创建一个名称为 httpServletRequestDemo 的项目,在 net.biancheng.www 包中创建一个名为 RequestLine 的 Servlet 类,代码如下。
- package net.biancheng.www;
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- @WebServlet("/RequestLine")
- public class RequestLine extends HttpServlet {
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- PrintWriter writer = response.getWriter();
- writer.println("请求方式:" + request.getMethod() + "<br/>" +
- "客户端的 IP 地址:" + request.getRemoteAddr() + "<br/>" +
- "应用名字(上下文):" + request.getContextPath() + "<br/>" +
- "URI:" + request.getRequestURI() + "<br/>" +
- "请求字符串:" + request.getQueryString() + "<br/>" +
- "Servlet所映射的路径:" + request.getServletPath() + "<br/>" +
- "客户端的完整主机名:" + request.getRemoteHost() + "<br/>"
- );
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- doGet(request, response);
- }
- }
启动 Tomcat 服务器,在地址栏中输入“http://localhost:8080/httpServletRequestDemo/RequestLine?a=1&b=2”,访问 RequestLine,结果如下图。
![](https://img2022.cnblogs.com/blog/2589330/202208/2589330-20220830133811864-1950132713.png)
获取请求头信息
当浏览器发送请求时,需要通过请求头向服务器传递一些附加信息,例如客户端可以接收的数据类型、压缩方式、语言等。为了获取请求头中的信息, HttpServletRequest 接口定义了一系列用于获取 HTTP 请求头字段的方法,如下表所示。返回值类型 | 方法声明 | 描述 |
---|---|---|
String | getHeader(String name) | 该方法用于获取一个指定头字段的值。 如果请求消息中包含多个指定名称的头字段,则该方法返回其中第一个头字段的值。 |
Enumeration | getHeaders(String name) | 该方法返回指定头字段的所有值的枚举集合, 在多数情况下,一个头字段名在请求消息中只出现一次,但有时可能会出现多次。 |
Enumeration | getHeaderNames() | 该方法返回请求头中所有头字段的枚举集合。 |
String | getContentType() | 该方法用于获取 Content-Type 头字段的值。 |
int | getContentLength() | 该方法用于获取 Content-Length 头字段的值 。 |
String | getCharacterEncoding() | 该方法用于返回请求消息的字符集编码 。 |
示例 2
为了更好地理解这些方法,下面通过案例演示这些方法的使用。在 net.biancheng.www 包中创建一个名为 RequestHeader 的 Servlet 类,代码如下。
- package net.biancheng.www;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.util.Enumeration;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- @WebServlet("/RequestHeader")
- public class RequestHeader extends HttpServlet {
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- PrintWriter writer = response.getWriter();
- //获得所有请求头字段的枚举集合
- Enumeration<String> headers = request.getHeaderNames();
- while (headers.hasMoreElements()) {
- //获得请求头字段的值
- String value = request.getHeader(headers.nextElement());
- writer.write(headers.nextElement() + ":" + value + "<br/>");
- }
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- doGet(request, response);
- }
- }
启动 Tomcat 服务器,在地址栏中输入“http://localhost:8080/httpServletRequestDemo/RequestHeader”,访问 RequestHeader ,结果如下图。
![](https://img2022.cnblogs.com/blog/2589330/202208/2589330-20220830133827446-274940149.png)
获取 form 表单的数据
在实际开发中,我们经常需要获取用户提交的表单数据,例如用户名和密码等。为了方便获取表单中的请求参数,ServletRequest 定义了一系列获取请求参数的方法,如下表所示。返回值类型 | 方法声明 | 功能描述 |
---|---|---|
String | getParameter(String name) | 返回指定参数名的参数值。 |
String [ ] | getParameterValues (String name) | 以字符串数组的形式返回指定参数名的所有参数值(HTTP 请求中可以有多个相同参数名的参数)。 |
Enumeration | getParameterNames() | 以枚举集合的形式返回请求中所有参数名。 |
Map | getParameterMap() | 用于将请求中的所有参数名和参数值装入一个 Map 对象中返回。 |
示例 3
为了更好地理解这些方法,下面通过案例演示这些方法的使用。在 httpServletRequestDemo 的 WebContent 目录下,创建 form.html,代码如下。
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>Insert title here</title>
- </head>
- <body>
- <form action="/httpServletRequestDemo/RequestParam" method="post">
- <table border="1" width="50%">
- <tr>
- <td colspan="2" align="center">编程帮wwww.biancheng.net</td>
- </tr>
- <tr>
- <td>输入姓名</td>
- <td><input type="text" name="username" /></td>
- </tr>
- <tr>
- <td>输入密码</td>
- <td><input type="password" name="password" /></td>
- </tr>
- <tr>
- <td>选择性别</td>
- <td><input type="radio" name="sex" value="male" />男 <input
- type="radio" name="sex" value="female" />女</td>
- </tr>
- <tr>
- <td>选择使用的语言</td>
- <td><input type="checkbox" name="language" value="JAVA" />JAVA
- <input type="checkbox" name="language" value="C" />C语言 <input
- type="checkbox" name="language" value="PHP" />PHP <input
- type="checkbox" name="language" value="Python" />Python</td>
- </tr>
- <tr>
- <td>选择城市</td>
- <td><select name="city">
- <option value="none">--请选择--</option>
- <option value="beijing">北京</option>
- <option value="shanghai">上海</option>
- <option value="guangzhou">广州</option>
- </select></td>
- </tr>
- <tr>
- <td colspan="2"><input type="submit" value="提交" /></td>
- </tr>
- </table>
- </form>
- </body>
- </html>
在 net.biancheng.www 包中,创建一个名为 RequestParam 的 Servlet 类,代码如下。
- package net.biancheng.www;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.util.Arrays;
- import java.util.Map;
- import java.util.Set;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- @WebServlet("/RequestParam")
- public class RequestParam extends HttpServlet {
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- PrintWriter writer = response.getWriter();
- // 获取内容,做其他操作
- // 获取姓名
- String username = request.getParameter("username");
- // 获取密码
- String password = request.getParameter("password");
- // 获取性别
- String sex = request.getParameter("sex");
- // 获取城市
- String city = request.getParameter("city");
- // 获取语言
- String[] languages = request.getParameterValues("language");
- writer.write("用户名:" + username + "<br/>" + "密码:" + password + "<br/>" + "性别:" + sex + "<br/>" + "城市:" + city
- + "<br/>" + "使用过的语言:" + Arrays.toString(languages) + "<br/>");
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
启动 Tomcat 服务器,在地址栏中输入“http://localhost:8080/httpServletRequestDemo/form.html”,即可访问 form.html,结果如下图。
![](https://img2022.cnblogs.com/blog/2589330/202208/2589330-20220830133845386-935939539.png)
![](https://img2022.cnblogs.com/blog/2589330/202208/2589330-20220830133903835-21556763.png)
中文乱码问题
如果在 form 表单输入框中输入中文,例如在输入姓名时,填写“编程帮默认用户”,点击提交后就会出现乱码问题,如下图所示。![](http://c.biancheng.net/uploads/allimg/210627/110352I32-5.png)
![](https://img2022.cnblogs.com/blog/2589330/202208/2589330-20220830133914887-424233179.png)
POST 请求
乱码的原因:POST 提交的数据在请求体中,其所使用的编码格式时页面一致(即 utf-8)。request 对象接收到数据之后,会将数据放到 request 缓冲区,缓冲区的默认字符集是 ISO-8859-1(该字符集不支持中文),两者使用的字符集不一致导致乱码。解决方案:在获取请求参数之前设置 request 缓冲区字符集为 utf-8 ,代码如下。
- //修改request缓冲区的字符集为UTF-8
- request.setCharacterEncoding("utf-8");
- // 获取用户名
- String username = request.getParameter("username");
GET 请求
乱码的原因:Get 请求将请求数据附加到 URL 后面作为参数,浏览器发送文字时采用的编码格式与页面编码保持一致(utf-8)。如果 Tomcat 没有设置字符集,接收 URL 时默认使用 ISO-8859-1 进行解码,ISO-8859-1 不兼容中文,无法正确解码,导致出现乱码。需要注意的是,在 Tomcat 8 中已解决了 get 方式提交请求中文乱码的问题,使用 Tomcat 8 及以上版本的同学不必再考虑此问题了,如果您使用的是 Tomcat 7 或更早的版本,出现乱码问题可以使用如下的方案解决。
解决方案:解决 GET 请求中文乱码问题,有以下 3 种解决方案。
1. 修改 tomcat/conf/server.xml 中的配置,代码如下。
- <Connector port="80" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443" URIEncoding="UTF-8"/>
- //得到TOMCAT通过ISO8859-1解码的字符串
- String username = request.getParameter("username");
- //对字符串使用ISO8859-1进行编码,得到最初浏览器使用UTF-8编码的字符串
- username = URLEncoder.encode(username, "ISO8859-1");
- //将使用UTF-8编码的字符串使用UTF-8进行解码,得到正确的字符串
- username = URLDecoder.decode(username, "UTF-8");
3. 使用 String 的构造方法:String(byte[] bytes, String charset) ,对字节数组(bytes)按照指定的字符集(charset)进行解码,返回解码后的字符串,解决乱码问题(推荐使用)。
- //获取姓名
- String username = request.getParameter("username");
- //使用String的构造方法解决乱码的问题
- username = new String(username.getBytes("ISO-8859-1"),"UTF-8");