一、Tomcat 请求响应基础
- Web 服务器接收到客户端 HTTP 请求后,会为每一次请求 单独创建
HttpServletRequest(请求对象)和HttpServletResponse(响应对象)。 request对象封装了客户端的请求数据,获取客户端提交数据需通过该对象实现。response对象封装了服务器对客户端的响应数据,向客户端输出数据需通过该对象实现。
二、HttpServletRequest 核心功能
HttpServletRequest是 Servlet 的service()方法参数之一,核心功能为封装请求数据、作为域对象存储数据、实现请求转发,其功能可分为四大类:封装请求头数据、封装请求正文数据、作为域对象、请求转发。
1. 获取请求头数据
- 核心方法由 Tomcat 封装到
request中,可在service()方法直接调用:String getHeader(String name):根据指定请求头名称获取对应值。Enumeration getHeaderNames():获取所有请求头的名称,可遍历获取所有请求头的键值对。
- 遍历示例:通过
getHeaderNames()获取所有请求头名称,再通过getHeader(name)逐个获取值,可打印到控制台或响应到页面。
2. 获取请求相关的其他核心方法
此类方法用于便捷获取请求头、请求 URL 相关数据,部分方法区分 GET/POST 请求(GET 无正文,部分方法返回 null/-1):
int getContentLength():获取请求正文字节数,GET 请求返回 - 1。String getContentType():获取请求类型,GET 返回 null,POST 默认返回application/x-www-form-urlencoded。String getMethod():返回请求方法,如 GET、POST、DELETE、PUT 等。Locale getLocale():返回客户端浏览器支持的区域信息,用于国际化开发。String getCharacterEncoding():获取请求编码,未设置时返回 null(默认 ISO-8859-1)。void setCharacterEncoding(String code):设置请求编码,仅对 POST 请求正文有效 ,需在调用getParameter()前执行。- 与请求 URL 相关方法(以
http://localhost:8080/hello/oneServlet?name=zhangSan为例):String getContextPath():返回项目上下文路径,例:/hello。String getQueryString():返回 URL 中的参数部分,例:name=zhangSan。String getRequestURI():返回请求 URI 路径,例:/hello/oneServlet。StringBuffer getRequestURL():返回完整请求 URL(无参数),例:http://localhost/hello/oneServlet。String getServletPath():返回 Servlet 访问路径,例:/oneServlet。
- 与客户端 / 服务器相关方法:
String getRemoteAddr():返回客户端 IP 地址。String getRemoteHost():返回客户端主机名(实际仍获取 IP)。int getRemotePort():返回客户端端口号(每次请求随机变化)。String getScheme():返回请求协议,例:http。String getServerName():返回服务器主机名,例:localhost。int getServerPort():返回服务器端口号,例:8080。
3. 获取客户端请求参数(精通)
(1)参数传递的两种方式
- GET 方式:地址栏直接拼接、超链接拼接、表单
method="GET"提交,参数在 URL 的 queryString 中,有长度限制。 - POST 方式:表单
method="POST"提交,参数在请求正文中,无长度限制,更安全。
(2)获取参数的核心方法
无论 GET/POST,获取参数的方法一致,方法适用于不同参数类型(单值 / 多值):
String getParameter(String name):通过参数名获取单值参数,如文本框、单选框、隐藏域。String[] getParameterValues(String name):通过参数名获取多值参数数组,如复选框(同一 name 对应多个 value)。Enumeration getParameterNames():获取所有请求参数的名称,可遍历获取所有单值 / 多值参数。Map<String, String[]> getParameterMap():获取所有参数的键值对 Map,key 为参数名,value 为参数值数组(统一处理单 / 多值参数)。
(3)单值参数接收
- 前台:表单 / 超链接传递单值参数,如
<input type="text" name="p1">。 - 后台:通过
getParameter(name)直接获取,可结合getParameterNames()/getParameterMap()遍历所有参数。
(4)多值参数接收
- 前台:复选框使用同一 name,如
<input type="checkbox" name="hobby" value="netplay">。 - 后台:通过
getParameterValues(name)获取字符串数组,或通过getParameterMap()遍历获取。
4. 中文乱码处理(熟练)
request 接收参数的乱码根源为编码不统一(默认 ISO-8859-1,不支持中文),GET/POST 请求处理方式不同,项目中通常统一使用 UTF-8 编码。
(1)POST 请求中文乱码
POST 参数在请求正文中,有两种处理方式,推荐第二种:
- 手动转码:先通过 ISO-8859-1 获取字节数组,再通过 UTF-8 重新编码为字符串。示例:
name = new String(name.getBytes("ISO-8859-1"),"UTF-8"); - 统一设置请求编码:在调用所有
getParameter()前执行request.setCharacterEncoding("UTF-8"),一次设置全局生效,仅对 POST 正文有效。
(2)GET 请求中文乱码
GET 参数在 URL 中,无请求正文,setCharacterEncoding()无效,有两种处理方式:
- 手动转码:与 POST 手动转码方式一致,对每个中文参数单独处理。
- 配置服务器编码:修改 Tomcat 的
/conf/server.xml,在<Connector>标签添加URIEncoding="UTF-8",对整个 Tomcat 的 GET 请求生效。 - 注意:Tomcat8.5 及以上版本已默认支持 URL 中文 UTF-8 编码,无需手动配置;不建议使用 GET 请求传递中文参数。
5. 请求转发与 request 作用域
(1)请求转发
- 概念:也叫服务器端跳转 ,Servlet 处理完业务逻辑后,通过
request跳转到目标资源(静态页面 / Servlet/JSP),地址栏不发生变化。 - 核心方法:
request.getRequestDispatcher("资源路径").forward(request, response); - 特点:跳转过程中可通过
request传递数据,目标资源能获取传递的属性值。
(2)request 作用域
request是域对象,作用范围仅在一次请求 - 响应过程中 ,每一次请求都会创建新的request对象,请求结束后对象销毁。- 数据操作方法:
void setAttribute(String name, Object value):向 request 域中存入键值对数据。Object getAttribute(String name):从 request 域中根据键获取数据。
- 与 ServletContext 对比:ServletContext 是全局域对象(服务器启动创建,关闭销毁),request 是局部域对象(一次请求有效),request 存数据更安全,不会造成数据共享冲突。
三、HttpServletResponse 核心功能
HttpServletResponse是 Servlet 的service()方法参数之一,核心作用是响应客户端请求,向客户端输出信息,封装了服务器的响应数据(响应头、状态码、响应正文),核心功能分为四类:设置响应头、发送状态码、设置响应正文、实现重定向。
1. 核心功能分类
- 设置响应头信息:如设置编码、刷新、重定向等响应头。
- 发送状态码:如 200(成功)、404(资源不存在)、500(服务器错误)。
- 设置响应正文:向客户端输出文本、HTML 等内容。
- 重定向:实现客户端跳转,地址栏发生变化。
2. 设置状态码和基础编码方法
response.setContentType("text/html;charset=utf-8"):核心方法,同时设置响应内容类型为 HTML、响应编码为 UTF-8,解决响应页面中文乱码,需在输出内容前执行。response.setCharacterEncoding("utf-8"):单独设置响应正文的编码,若未设置contentType,浏览器默认按 ISO-8859-1 解析,仍会乱码,通常与setContentType配合使用。response.setStatus(int sc):设置响应状态码,如response.setStatus(200)。response.sendError(int sc, String msg):发送错误状态码并携带提示信息,如response.sendError(404, "您要查找的资源不存在"),Tomcat 会跳转到对应错误页面并显示提示。
3. 设置响应头信息
response.setHeader(String name, String value):设置自定义响应头,与setContentType()功能一致(setContentType是便捷方法),例:response.setHeader("contentType", "text/html;charset=utf-8")。- 定时刷新 / 重定向:
response.setHeader("Refresh", "5; URL=http://www.baidu.com"),表示 5 秒后自动跳转到指定 URL。
4. 响应中文乱码处理
向客户端输出中文时,需先设置编码,再输出内容:
java
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().write("中文内容");
5. 重定向
- 概念:也叫客户端跳转 ,Servlet 处理完业务逻辑后,通过
response告诉客户端跳转到新的资源地址,客户端会重新发送请求,地址栏发生变化。 - 核心方法:
response.sendRedirect("资源路径")。 - 特点:重定向后原
request域中的数据全部失效,会创建新的request对象;支持跨域跳转(跳转到其他服务器的资源)。
四、请求转发(forward)与重定向(redirect)的区别(核心面试题)
1. 处理流程不同
- 请求转发:客户端发送 1 次请求 → 服务器 Servlet 处理业务 → 服务器内部跳转到目标资源 → 服务器将目标资源结果返回客户端(全程 1 次请求)。
- 重定向:客户端发送 1 次请求 → 服务器 Servlet 处理业务 → 服务器返回跳转地址给客户端 → 客户端重新发送 2 次请求到新地址 → 服务器返回新资源结果(全程 2 次请求)。
2. 地址栏表现不同
- 请求转发:地址栏不变,始终显示第一次请求的地址(服务器端内部跳转,客户端无感知)。
- 重定向:地址栏变为新资源地址,客户端能看到跳转后的地址。
3. 绝对路径中 "/" 的含义不同
- 请求转发:服务器内部跳转,
/代表当前 Web 应用的根目录 ,例:/success.jsp(直接指向项目下的 success.jsp)。 - 重定向:客户端重新请求,
/代表Tomcat 服务器的根目录 ,例:需写/项目名/资源名(/param_demo/success.html)。 - 相对路径:两者使用无区别,均基于当前页面路径解析。
4. 数据传递不同
- 请求转发:属于同一次请求,可通过
request.setAttribute()/getAttribute()传递数据(request 作用域有效)。 - 重定向:属于两次不同请求,原 request 域数据失效,无法通过 request 传递数据,需使用 session 或 URL 拼接参数。
5. 跳转范围不同
- 请求转发:仅能跳转到当前 Web 应用内部的资源,无法跨域(如跳转到百度)。
- 重定向:支持跨域跳转,可跳转到任意服务器的资源(如百度、其他项目)。
6. 效率与方法归属不同
- 效率:请求转发效率更高(仅 1 次请求,服务器内部处理),重定向效率较低(2 次请求,客户端与服务器交互),能使用转发时优先使用。
- 方法归属:
- 转发:
request.getRequestDispatcher().forward(),属于请求对象的方法,请求过程未结束。 - 重定向:
response.sendRedirect(),属于响应对象的方法,调用时表示第一次请求已结束,服务器开始返回响应。
- 转发: