Request 与 Response 完全指南

一、Tomcat 请求响应机制

1.1 Request 和 Response 对象的创建

当 Web 服务器(如 Tomcat)接收到客户端的 HTTP 请求时,会针对每一次请求分别创建两个对象:

HttpServletRequest request:代表请求对象,封装了客户端发送给服务器的所有请求数据(请求行、请求头、请求体等)。

HttpServletResponse response:代表响应对象,封装了服务器要返回给客户端的所有响应数据(状态码、响应头、响应体等)。

这两个对象由 Tomcat 创建,并作为参数传递给 Servlet 的 service() 方法(以及 doGet()、doPost() 等方法)。开发者可以直接使用它们来获取请求数据和设置响应数据。

1.2 Request 和 Response 的作用

Request 和 Response 是 Servlet 开发中最核心的两个对象,它们的作用可以概括为:

Request 的作用:

获取客户端提交的请求参数(表单数据、URL 参数等)。

获取请求头信息(User-Agent、Referer、Cookie 等)。

获取客户端信息(IP 地址、端口号等)。

作为域对象在请求转发过程中共享数据。

Response 的作用:

向客户端输出响应内容(HTML、JSON、文本等)。

设置响应状态码(200、404、500 等)。

设置响应头信息(Content-Type、Refresh、Location 等)。

实现重定向。

二、HttpServletRequest 基本功能

2.1 Request 的四大功能

HttpServletRequest 在 JavaWeb 开发中极为重要,它是 Servlet 中处理请求的核心对象。它的功能可以归纳为以下四类:

功能一:封装了请求头数据

可以获取浏览器发送的所有 HTTP 请求头信息。

功能二:封装了请求正文数据

对于 POST 请求,可以获取请求体中的参数数据。GET 请求没有请求体。

功能三:是一个域对象

可以像 Map 一样存储和获取数据,在请求转发过程中共享数据。

功能四:实现请求转发

可以将请求转发到另一个 Servlet、JSP 或 HTML 页面,实现服务器内部的跳转。

2.2 获取请求头数据

通过 Request 对象可以获取客户端发送的所有请求头信息。

核心方法:

String getHeader(String name):获取指定名称的请求头值。

Enumeration getHeaderNames():获取所有请求头的名称集合。

代码示例:

复制代码
response.setContentType("text/html;charset=utf-8");
Enumeration names = request.getHeaderNames();
while (names.hasMoreElements()) {
    String name = (String) names.nextElement();
    String value = request.getHeader(name);
    System.out.println(name + ": " + value);
    response.getWriter().println(name + ": " + value + "<br/>");
}

常见请求头说明:

User-Agent:浏览器类型和版本信息。

Referer:请求来源页面地址。

Cookie:客户端保存的 Cookie 数据。

Host:请求的目标主机和端口。

Accept-Language:客户端支持的语言。

2.3 获取请求相关的其他方法

Request 对象提供了大量与请求相关的方法,下面按功能分类列出:

与请求 URL 相关的方法:

String getContextPath():获取上下文路径(项目名称),例如 /demo。

String getRequestURI():获取请求 URI 路径,例如 /demo/login。

StringBuffer getRequestURL():获取完整的请求 URL,例如 http://localhost:8080/demo/login。

String getServletPath():获取 Servlet 映射路径,例如 /login。

String getQueryString():获取 URL 中的参数字符串,例如 name=zhangsan&age=18。

与请求方法相关的方法:

String getMethod():获取请求方法,例如 GET、POST、PUT、DELETE。

与客户端信息相关的方法:

String getRemoteAddr():获取客户端 IP 地址。

String getRemoteHost():获取客户端主机名。

int getRemotePort():获取客户端端口号。

与服务器信息相关的方法:

String getScheme():获取请求协议,例如 http 或 https。

String getServerName():获取服务器主机名。

int getServerPort():获取服务器端口号。

与请求编码相关的方法:

String getCharacterEncoding():获取请求编码,默认返回 null(表示 ISO-8859-1)。

void setCharacterEncoding(String code):设置请求编码,只对 POST 请求的正文有效。

与请求内容相关的方法:

int getContentLength():获取请求正文的字节数,GET 请求返回 -1。

String getContentType():获取请求内容类型,POST 默认为 application/x-www-form-urlencoded。

Locale getLocale():获取客户端浏览器支持的语言和地区。

三、HttpServletRequest 获取参数

3.1 传递参数的两种方式:GET 和 POST

在 Web 开发中,客户端向服务器传递参数主要有两种方式:

GET 方式传参(参数在 URL 中可见):

方式一:地址栏直接拼接参数

http://localhost/param/ParamServlet?p1=v1\&p2=v2

方式二:超链接携带参数

<a href="http://localhost/param/ParamServlet?p1=v1\&p2=v2">点击</a>

方式三:表单 method="GET"

<form method="GET" action="ParamServlet">...</form>

POST 方式传参(参数在请求体中,不可见):

方式一:表单 method="POST"

<form method="POST" action="ParamServlet">...</form>

3.2 获取参数的核心方法

Request 对象提供了以下四个核心方法来获取请求参数:

方法一:String getParameter(String name)

通过参数名获取单个参数值。适用于文本框、密码框、单选按钮、下拉框等单值控件。

方法二:String\[\] getParameterValues(String name)

通过参数名获取参数值数组。适用于复选框等可能传递多个值的控件。

方法三:Enumeration getParameterNames()

获取所有参数名的枚举集合。

方法四:Map<String, String\[\]> getParameterMap()

获取所有参数组成的 Map,键为参数名,值为参数值数组。

3.3 单值参数接收

单值参数包括:文本框、密码框、隐藏域、单选按钮、单值下拉框等。

复制代码
前台页面示例(GET 和 POST 均可):
<form action="ParamServlet" method="post">
    <input type="text" name="p1"/><br/>
    <input type="text" name="p2"/><br/>
    <input type="submit" value="提交"/><br/>
</form>

超链接传参:
<a href="ParamServlet?p1=v1&p2=v2">Param</a>

后台接收代码:
String s1 = request.getParameter("p1");
String s2 = request.getParameter("p2");
response.getWriter().print("p1 = " + s1 + "<br/>");
response.getWriter().print("p2 = " + s2 + "<br/>");

3.4 多值参数接收

复选框(checkbox)是最典型的多值参数,多个复选框可以使用相同的 name

3.5 获取所有参数的通用方式

使用 getParameterNames() 或 getParameterMap() 可以遍历所有参数,适合参数名未知或动态参数的场景。

方式一:使用 Enumeration 遍历

复制代码
Enumeration names = request.getParameterNames();
while (names.hasMoreElements()) {
    String name = (String) names.nextElement();
    String value = request.getParameter(name);
    System.out.println(name + " = " + value);
}

方式二:使用 Map 遍历

复制代码
Map<String, String[]> map = request.getParameterMap();
Set<String> keySet = map.keySet();
for (String key : keySet) {
    String[] vals = map.get(key);
    System.out.println(key + " : " + Arrays.toString(vals));
}

四、中文乱码处理

4.1 POST 请求中文乱码解决方案

POST 请求的参数在请求体中传输,默认使用 ISO-8859-1 编码,导致中文乱码。有两种解决方案:

复制代码
方案一:手动转码(通用,但较繁琐)
String name = request.getParameter("name");
// 先用 ISO-8859-1 获取字节数组,再用 UTF-8 重新构造字符串
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("name: " + name);

方案二:设置请求编码(推荐,简洁高效)
// 必须在调用 getParameter() 之前设置
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
System.out.println("name: " + name);

注意:request.setCharacterEncoding() 只对 POST 请求的请求体有效,对 GET 请求无效。

4.2 GET 请求中文乱码解决方案

GET 请求的参数在 URL 的 queryString 中,不存在请求体,所以 setCharacterEncoding() 无效。有两种解决方案:

方案一:手动转码(与 POST 相同)

复制代码
String name = request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("name: " + name);

方案二:修改 Tomcat 配置文件(推荐)

在 Tomcat 的 conf/server.xml 中,修改 Connector 配置,添加 URIEncoding 属性:

复制代码
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding="UTF-8"/>

配置后,所有 GET 请求的参数都会使用 UTF-8 解码,无需再手动转码。

五、请求转发与 Request 域对象

5.1 请求转发(RequestDispatcher)

请求转发(Forward)是服务器内部的跳转方式,由 Request 对象发起。它发生在服务器内部,客户端浏览器并不知道发生了跳转,地址栏不会发生变化。

基本语法:

request.getRequestDispatcher("/目标路径").forward(request, response);

示例:跳转到 success.html

request.getRequestDispatcher("/success.html").forward(request, response);

示例:跳转到另一个 Servlet

request.getRequestDispatcher("/otherServlet").forward(request, response);

请求转发的特点:

服务器内部跳转,浏览器地址栏不变。

整个过程处于同一个请求中,Request 域对象中的数据可以共享。

只能跳转到当前 Web 应用内部的资源。

效率比重定向高(减少了客户端与服务器的一次往返)。

5.2 Request 域对象的作用范围

Request 是一个域对象,可以在请求转发过程中存储和传递数据。

存储数据:

request.setAttribute("name", "张三");

获取数据:

String name = (String) request.getAttribute("name");

Request 域对象的生命周期:

创建:客户端发送请求时,Tomcat 创建 Request 对象。

销毁:服务器处理完请求并返回响应后,Request 对象被销毁。

范围:仅在一次请求中有效,请求转发时数据可以传递到目标资源。

三大域对象范围对比(从小到大):

HttpServletRequest(请求域) < HttpSession(会话域) < ServletContext(应用域)

六、HttpServletResponse

6.1 Response 的四大功能

HttpServletResponse 是响应对象,用于向客户端输出数据。它的功能可以分为以下四类:

功能一:设置响应头信息

可以设置各种响应头,如 Content-Type、Refresh、Location 等。

功能二:发送状态码

可以设置响应状态码(200、404、500 等)。

功能三:设置响应正文

通过 getWriter() 或 getOutputStream() 向客户端输出内容。

功能四:实现重定向

通过 sendRedirect() 方法将客户端重定向到另一个资源。

6.2 设置状态码

Response 提供了设置和发送状态码的方法:

设置正常状态码:

response.setStatus(200); // 正常响应,通常无需手动设置

发送错误状态码:

response.sendError(404, "您要查找的资源不存在");

response.sendError(500, "服务器内部错误");

设置响应类型和编码:

// 设置响应类型为 HTML,编码为 UTF-8

response.setContentType("text/html;charset=utf-8");

// 单独设置编码(与上面配合使用)

response.setCharacterEncoding("UTF-8");

6.3 设置响应头信息

通过 Response 可以设置各种 HTTP 响应头:

设置 Content-Type:

response.setHeader("Content-Type", "text/html;charset=utf-8");

// 等价于 response.setContentType("text/html;charset=utf-8");

设置定时刷新(5秒后跳转到百度):

response.setHeader("Refresh", "5; URL=http://www.baidu.com");

设置禁用缓存:

response.setHeader("Cache-Control", "no-cache");

response.setHeader("Pragma", "no-cache");

response.setDateHeader("Expires", -1);

6.4 Response 中文乱码处理

使用 Response 向客户端输出中文时,如果未设置正确的编码,会出现乱码。解决方法:

方法一:使用 setContentType(推荐)

复制代码
// 同时设置响应类型和编码
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("张三");

方法二:分别设置

复制代码
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "text/html;charset=UTF-8");
response.getWriter().write("张三");

注意:setContentType 必须在 getWriter() 之前调用才有效。

七、重定向(Response 的核心功能)

7.1 重定向的基本使用

重定向(Redirect)是通过 Response 对象实现的一种页面跳转方式。它本质上是服务器向客户端发送一个 302 状态码和 Location 响应头,告诉浏览器重新向另一个地址发送请求。

基本语法:

复制代码
response.sendRedirect("目标路径");

示例:
// 重定向到 success.html
response.sendRedirect("/demo/success.html");

// 重定向到另一个 Servlet
response.sendRedirect("/demo/otherServlet");

// 重定向到外部网站
response.sendRedirect("http://www.baidu.com");

7.2 重定向的特点

重定向具有以下特点:

客户端行为,浏览器地址栏会发生变化,显示新的 URL。

两次请求:第一次请求返回重定向响应,第二次请求访问目标资源。

不共享 Request 域数据:两次请求是独立的,Request 域中的数据无法传递。

可以跨域访问:可以重定向到外部网站(如百度)。

可以重定向到任意资源,不限于当前 Web 应用。

相关推荐
启扶农7 个月前
lecen:一个更好的开源可视化系统搭建项目--数据、请求、寄连对象使用--全低代码|所见即所得|利用可视化设计器构建你的应用系统-做一个懂你的人
低代码·数据对象·数据访问·页面可视化·页面设计器·请求对象·寄连对象