HttpServletRequest接口和HttpServletResponse接口-12

目录

一、HttpServletRequest接口详解

1、获取请求行信息

2、获取请求头信息

3、获取 form 表单的数据

4、request 中文乱码问题

二、HttpServletResponse接口详解

1、响应行相关的方法

2、响应头相关的方法

3、响应体相关的方法

4、response 中文乱码问题


        一般情况下,浏览器(客户端)通过 HTTP 协议来访问服务器的资源,Servlet 主要用来处理 HTTP 请求。Servlet 处理 HTTP 请求的流程如下:

  1. Servlet 容器接收到来自客户端的 HTTP 请求后,容器会针对该请求分别创建一个 HttpServletRequest 对象和 HttpServletResponse 对象。
  2. 容器将 HttpServletRequest 对象和 HttpServletResponse 对象以参数的形式传入 service() 方法内,并调用该方法。
  3. 在 service() 方法中 Servlet 通过 HttpServletRequest 对象获取客户端信息以及请求的相关信息。
  4. 对 HTTP 请求进行处理。
  5. 请求处理完成后,将响应信息封装到 HttpServletResponse 对象中。
  6. Servlet 容器将响应信息返回给客户端。
  7. 当 Servlet 容器将响应信息返回给客户端后,HttpServletRequest 对象和 HttpServletResponse 对象被销毁。

        通过以上流程可以看出, HttpServletRequest 和 HttpServletResponse 是 Servlet 处理 HTTP 请求过程中最重要的两个对象。前者用于封装 HTTP 请求信息,后者用于封装 HTTP 响应信息。

一、HttpServletRequest接口详解

        在 Servlet API 中,定义了一个 HttpServletRequest 接口,它继承自 ServletRequest 接口。HttpServletRequest 对象专门用于封装 HTTP 请求信息,简称 request 对象。

        HTTP 请求信息分为请求行、请求消息头和请求消息体三部分,在 HttpServletRequest 接口中定义了获取请求行、请求头和请求消息体的相关方法。

1、获取请求行信息

        HTTP 请求的请求行中包含请求方法、请求资源名、请求路径等信息,HttpServletRequest 接口定义了一系列获取请求行信息的方法,如下表:

返回值类型方法描述
StringgetMethod()该方法用于获取 HTTP 请求方式(如 GET、POST 等)。
StringgetRequestURI()该方法用于获取请求行中的资源名称部分,即位于 URL 的主机和端口之后,参数部分之前的部分。
StringgetQueryString()该方法用于获取请求行中的参数部分,也就是 URL 中 "?" 以后的所有内容。
StringgetContextPath()返回当前 Servlet 所在的应用的名字(上下文)。对于默认(ROOT)上下文中的 Servlet,此方法返回空字符串""。
StringgetServletPath()该方法用于获取 Servlet 所映射的路径。
StringgetRemoteAddr()该方法用于获取客户端的 IP 地址。
StringgetRemoteHost()该方法用于获取客户端的完整主机名,如果无法解析出客户机的完整主机名,则该方法将会返回客户端的 IP 地址。

        下面通过示例演示这些方法的使用,代码如下所示:

package com.hoperun.www;

import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/ReadRequestLine")
public class HttpServletRequestDemo 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.write(
				"请求方式:" + request.getMethod() + "<br/>" + 
				"URI:" + request.getRequestURI() + "<br/>" + 
				"请求字符串:" + request.getQueryString() + "<br/>" + 
				"应用名称(上下文):" + request.getContextPath() + "<br/>" + 
				"Servlet所映射的路径:" + request.getServletPath() + "<br/>" + 
				"客户端的 IP 地址:" + request.getRemoteAddr() + "<br/>" + 
				"客户端的完整主机名:" + request.getRemoteHost());

		writer.close();
	}

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

}

        启动 Tomcat 服务器,在地址栏中输入http://localhost:8080/servletDemo/ReadRequestLine?a=1&b=2,访问 ReadRequestLine,结果如下图:

2、获取请求头信息

        当浏览器发送请求时,需要通过请求头向服务器传递一些附加信息。例如客户端可以接收的数据类型、压缩方式、语言等。为了获取请求头中的信息, HttpServletRequest 接口定义了一系列用于获取 HTTP 请求头字段的方法,如下表所示:

返回值类型方法描述
StringgetHeader(String name)该方法用于获取一个指定头字段的值。
如果请求消息中包含多个指定名称的头字段,则该方法返回其中第一个头字段的值。
EnumerationgetHeaders(String name)该方法返回指定头字段的所有值的枚举集合,
在多数情况下,一个头字段名在请求消息中只出现一次,但有时可能会出现多次。
EnumerationgetHeaderNames()该方法返回请求头中所有头字段的枚举集合。
StringgetContentType()该方法用于获取 Content-Type 头字段的值。
intgetContentLength()该方法用于获取 Content-Length 头字段的值。
StringgetCharacterEncoding()该方法用于返回请求消息的字符集编码 。

        下面通过示例演示这些方法的使用,代码如下所示:

package com.hoperun.www;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/ReadRequestHeader")
public class HttpServletRequestDemo 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/>");
        }
        writer.write("Content-Type:" + request.getContentType() + "<br/>");
        writer.write("Content-Length:" + request.getContentLength() + "<br/>");
        writer.write("CharacterEncoding:" + request.getCharacterEncoding() + "<br/>");
		writer.close();
	}

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

}

        启动 Tomcat 服务器,在地址栏中输入http://localhost:8080/servletDemo/ReadRequestHeader,访问 ReadRequestHeader ,结果如下图:

3、获取 form 表单的数据

        在实际开发中,我们经常需要获取用户提交的表单数据。例如用户名、密码等。为了方便获取表单中的请求参数,ServletRequest 定义了一系列获取请求参数的方法,如下表所示:

返回值类型方法描述
StringgetParameter(String name)返回指定参数名的参数值。
String[]getParameterValues (String name)以字符串数组的形式返回指定参数名的所有参数值(HTTP 请求中可以有多个相同参数名的参数)。
Enumeration<String>getParameterNames()以枚举集合的形式返回请求中所有参数名。
Map<String, String[]>getParameterMap()用于将请求中的所有参数名和参数值装入一个 Map 对象中返回。

示例:

1)在 servletDemo 的 Webapp 目录下,创建 form.html,代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>收集个人信息</title>
</head>
<body>
<form action="/servletDemo/ReadRequestParam" method="post">
        <table border="1">
            <tr>
                <td colspan="2" align="center">个人信息</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>

2)创建一个名为 ReadRequestParam 的 Servlet 类,代码如下:

package com.hoperun.www;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/ReadRequestParam")
public class HttpServletRequestDemo 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));
		writer.close();
	}

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

}

        启动 Tomcat 服务器,在地址栏中输入http://localhost:8080/servletDemo/form.html,即可访问 form.html,结果如下图:

 在表单中填写信息后,点击提交,结果如下图:

4、request 中文乱码问题

        如果在 form 表单输入框中输入中文。例如:输入姓名时,填写"用户名",点击提交后就会出现乱码问题。对于GET 请求和 POST 请求,这两种请求方式都可能会产生中文乱码问题,下面我们分别对它们产生乱码的原因及其解决方案进行介绍:

1)POST 请求

  • 乱码的原因:POST 提交的数据在请求体中,其所使用的编码格式与页面一致(即 utf-8)。request 对象接收到数据之后,会将数据放到 request 缓冲区,缓冲区的默认字符集是 ISO-8859-1(该字符集不支持中文),两者使用的字符集不一致导致乱码。
  • 解决方案:在获取请求参数之前设置 request 缓冲区字符集为 utf-8 ,代码如下:

// 修改request缓冲区的字符集为UTF-8
request.setCharacterEncoding("utf-8");
// 获取用户名
String username = request.getParameter("username");

2)GET 请求

        乱码的原因:Get 请求将请求数据附加到 URL 后面作为参数,浏览器发送请求时采用的编码格式与页面编码保持一致(utf-8)。如果 Tomcat 没有设置字符集,接收 URL 时默认使用 ISO-8859-1 进行解码,ISO-8859-1 不兼容中文,无法正确解码,导致出现乱码。

需要注意的是,在 Tomcat 8 中已解决了 get 方式提交请求中文乱码的问题,使用 Tomcat 8 及以上版本的同学不必再考虑此问题了,如果您使用的是 Tomcat 7 或更早的版本,出现乱码问题可以使用如下的方案解决。

解决方案:解决 GET 请求中文乱码问题,有以下 3 种解决方案。 

  • 修改 tomcat/conf/server.xml 中的配置,代码如下:
<Connector port="80" protocol="HTTP/1.1"
         connectionTimeout="20000"
           redirectPort="8443" URIEncoding="UTF-8"/>
  • 使用 URLEncoder 和 URLDecoder 进行编码和解码的操作(逆向编解码),代码如下:
// 得到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");
  • 使用 String 的构造方法:String(byte[] bytes, String charset) ,对字节数组(bytes)按照指定的字符集(charset)进行解码,返回解码后的字符串,解决乱码问题(推荐使用),代码如下:
// 获取姓名
String username = request.getParameter("username");
// 使用String的构造方法解决乱码的问题
username = new String(username.getBytes("ISO-8859-1"), "UTF-8");

二、HttpServletResponse接口详解

        在 Servlet API 中,定义了一个 HttpServletResponse 接口,它继承自 ServletResponse 接口。HttpServletResponse 对象专门用来封装 HTTP 响应信息,简称 response 对象。
        Servlet 容器会针对每次请求创建一个 response 对象,并把它作为参数传递给 Servlet 的 service 方法。Servlet 处理请求后,会将响应信息封装到 response 对象中,并由容器解析后返回给客户端。
        HTTP 响应消息由响应行、响应头、消息体三部分组成,所以 HttpServletResponse 接口中定义了向客户端发送响应状态码、响应头、响应体的方法,下面我们对这些方法进行介绍。

1、响应行相关的方法

        当 Servlet 返回响应消息时,需要在响应消息中设置状态码。因此,HttpServletResponse 接口定义了发送状态码的方法,如下表:

返回值类型方法描述
voidsetStatus(int sc)用于设置 HTTP 响应消息的状态码,并生成响应状态行。
voidsendError(int sc)用于发送表示错误信息的状态码。

2、响应头相关的方法

        HttpServletResponse 接口中定义了一系列设置 HTTP 响应头字段的方法,如下表所示:

返回值类型方法描述
voidaddHeader(String name,String value)用于增加响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值。
voidsetHeader (String name,String value)用于设置响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值。
voidaddIntHeader(String name,int value)用于增加值为 int 类型的响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值,类型为 int。
voidsetIntHeader(String name, int value)用于设置值为 int 类型的响应头字段,其中,参数 name 用于指定响应头字段的名称,参数 value 用于指定响应头字段的值,类型为 int。
voidsetContentType(String type)用于设置 Servlet 输出内容的 MIME 类型以及编码格式。
voidsetCharacterEncoding(String charset)用于设置输出内容使用的字符编码。

3、响应体相关的方法

        由于在 HTTP 响应消息中,大量的数据都是通过响应消息体传递的。因此 ServletResponse 遵循以 I/O 流传递大量数据的设计理念,在发送响应消息体时,定义了两个与输出流相关的方法。

返回值类型方法描述
ServletOutputStreamgetOutputStream()用于获取字节输出流对象。
PrintWritergetWriter()用于获取字符输出流对象。 

注意:getOutputStream() 和 getWriter() 方法互相排斥,不可同时使用,否则会发生 IllegalStateException 异常。

        启动 Tomat 服务器,在客户端浏览器地址栏输入http://localhost:8080/servletDemo/testHttpServletResponse,访问 testHttpServletResponse,结果如下图:

        在 doGet() 方法中调用 output2() 方法,使用字符流输出响应内容到浏览器,再次访问 testHttpServletResponse,结果如下图:

4、response 中文乱码问题

        response 对象向页面输出时有两种方式:字节流、字符流,这两种方式输出中文时都有可能出现乱码。

1)使用字节流输出中文

        使用字节流向页面输出中文是否会出现乱码问题?不一定。

ServletOutputStream outptuStream = response.getOutputStream();
outputStream.write("你好 www.csdn.net".getBytes());

乱码原因:

        字节流输出中文是否出现乱码,取决于中文转成字节数组时与浏览器打开时采用的字符集是否一致。若两者保持一致,则不会出现乱码问题,若不一致就会出现乱码问题。

解决方案:

        将中文转成字节数组时和浏览器默认采用的字符集保持一致即可,代码如下:

response.setHeader("Content-Type", "text/html;charset=UTF-8");
// 获取字节输出流
OutputStream os = response.getOutputStream();
byte[] str = "你好 www.csdn.net".getBytes("UTF-8");
// 输出中文
os.write(str);

2)使用字符流输出中文

        使用字符流向页面输出中文是否会出现乱码问题?一定乱码。

乱码原因:

        通过字符流输出的内容是存放在 response 缓冲区的,response 缓冲区的默认字符集是 ISO-8859-1,该字符集不支持中文。

解决方案:

        将 response 缓冲区和浏览器采用的字符集保持一致即可,有如下 2 种的方式。

第一种方式:

// 设置response缓冲区的编码
response.setCharacterEncoding("UTF-8");
// 设置浏览器打开文件所采用的编码
response.setHeader("Content-Type", "text/html;charset=UTF-8");
// 输出中文
response.getWriter().write("你好 www.csdn.net");

第二种方式:

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("你好 www.csdn.net");
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值