请求

Java Web 请求处理:HttpServletRequest 详解

在 Java Web 开发中,客户端的 HTTP 请求由 HttpServletRequest 对象封装,它提供了丰富的方法用于获取请求行、请求头、请求参数等信息。本文将系统梳理 HttpServletRequest 的核心功能,包括请求行解析、请求头获取、参数处理及会话管理等,帮助开发者高效处理客户端请求。

HttpServletRequest 概述

HttpServletRequest 是 ServletRequest 接口的子接口,专门用于处理 HTTP 协议的请求。它由 Servlet 容器创建并传递给 service() 方法,包含客户端请求的所有信息(如 URL、参数、 headers 等)。

// HttpServlet 中处理请求的方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
    // 通过 req 处理请求...
}

请求行信息获取

HTTP 请求行由请求方法(如 GET/POST)、请求 URI 和协议版本组成(如 GET /index.jsp HTTP/1.1)。HttpServletRequest 提供以下方法解析请求行:

方法 作用描述 示例(假设请求为 GET /app/user?id=1 HTTP/1.1)
getMethod() 获取请求方法(GET/POST/PUT/DELETE 等) GET
getProtocol() 获取协议版本(如 HTTP/1.1) HTTP/1.1
getRequestURI() 获取请求 URI(主机名后的路径部分) /app/user
getRequestURL() 获取完整请求 URL(包含协议、主机、端口和路径) http://localhost:8080/app/user
getQueryString() 获取 URL 中的查询参数(? 后的部分) id=1
getContextPath() 获取当前 Web 应用的上下文路径(部署路径) /app
getServletPath() 获取 Servlet 映射的路径 /user
getPathInfo() 获取 URL 中 Servlet 路径后的额外路径信息(无则为 null) null(若请求为 /app/user/1,则返回 /1)

网络连接信息

获取客户端与服务器的网络连接细节,如 IP、端口等:

方法 作用描述
getRemoteAddr() 获取客户端 IP 地址
getRemoteHost() 获取客户端主机名(可能与 IP 相同,取决于 DNS 配置)
getRemotePort() 获取客户端端口号
getLocalAddr() 获取服务器接收请求的 IP 地址
getLocalPort() 获取服务器接收请求的端口号
getServerName() 获取请求指向的服务器主机名(如 localhost)
getServerPort() 获取服务器监听的端口号(如 8080)
getScheme() 获取协议名(如 http 或 https)

请求头信息处理

HTTP 请求头包含客户端的附加信息(如浏览器类型、数据类型等),HttpServletRequest 提供以下方法获取:

方法 作用描述
getHeader(String name) 获取指定名称的请求头值(如 User-Agent)
getHeaders(String name) 获取指定名称的所有请求头值(返回 Enumeration<String>)
getHeaderNames() 获取所有请求头的名称(返回 Enumeration<String>)
getIntHeader(String name) 获取整数类型的请求头(如 Content-Length)
getDateHeader(String name) 获取日期类型的请求头(返回毫秒时间戳,如 If-Modified-Since)
getContentLength() 获取 Content-Length 头的值(请求体长度,单位字节)
getContentType() 获取 Content-Type 头的值(如 application/x-www-form-urlencoded)
getCharacterEncoding() 获取请求体的字符编码(从 Content-Type 头提取,如 UTF-8)

示例:获取浏览器类型

String userAgent = request.getHeader("User-Agent");
// 输出:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...

请求参数处理

请求参数是客户端传递给服务器的数据,可通过 URL query 或请求体发送。HttpServletRequest 提供多种方法解析参数:

基本参数获取

方法 作用描述
getParameter(String name) 获取指定名称的参数值(适用于单值参数)
getParameterValues(String name) 获取指定名称的所有参数值(适用于多值参数,如复选框)
getParameterNames() 获取所有参数名称(返回 Enumeration<String>)
getParameterMap() 获取所有参数的键值对(返回 Map<String, String[]>)

示例:处理表单提交的参数

// 假设请求参数为:username=zhangsan&hobby=reading&hobby=sports
String username = request.getParameter("username"); // "zhangsan"
String[] hobbies = request.getParameterValues("hobby"); // ["reading", "sports"]
Map<String, String[]> paramMap = request.getParameterMap(); // 包含所有参数

原始请求体读取

对于非表单格式的请求(如 JSON、XML),需通过输入流直接读取请求体:

方法 作用描述
getInputStream() 获取请求体的字节输入流(ServletInputStream)
getReader() 获取请求体的字符输入流(BufferedReader,需指定编码)

示例:读取 JSON 请求体

// 设置字符编码
request.setCharacterEncoding("UTF-8");
// 通过字符流读取
BufferedReader reader = request.getReader();
StringBuilder json = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
    json.append(line);
}
String requestBody = json.toString(); // JSON 字符串

会话管理相关方法

HttpServletRequest 提供会话(HttpSession)相关方法,用于跟踪用户状态:

方法 作用描述
getSession() 获取当前会话,若不存在则创建新会话(等价于 getSession(true))
getSession(boolean create) 若 create=true,不存在则创建;create=false,不存在则返回 null
getRequestedSessionId() 获取请求中携带的会话 ID(从 Cookie 或 URL 中提取)
isRequestedSessionIdValid() 判断请求中的会话 ID 是否有效(对应会话是否存在)
changeSessionId() 更换当前会话的 ID(用于防止会话固定攻击)

示例:获取会话并存储用户信息

HttpSession session = request.getSession();
session.setAttribute("userId", 1001); // 存储用户 ID
Integer userId = (Integer) session.getAttribute("userId"); // 获取用户 ID

其他常用方法

方法 作用描述
getCookies() 获取请求中的所有 Cookie(返回 Cookie[])
getAuthType() 获取认证方式(如 BASIC、FORM)
getRemoteUser() 获取通过认证的用户名(如 HTTP 基本认证)
isUserInRole(String role) 判断当前用户是否属于指定角色(用于权限控制)
getParts() / getPart(String name) 处理文件上传(获取请求中的 multipart 部分,需 @MultipartConfig 注解)

注意事项

  1. 参数编码:
    • 对于 URL query 参数,需在服务器配置中指定编码(如 Tomcat 的 URIEncoding="UTF-8");
    • 对于 POST 请求体,需在读取参数前调用 request.setCharacterEncoding("UTF-8")。
  2. 参数获取时机:
    • getParameter() 方法会消耗请求体流,调用后 getInputStream() 或 getReader() 将返回空流,需注意调用顺序。
  3. 会话安全性:
    • 优先使用 Cookie 存储会话 ID(isRequestedSessionIdFromCookie()),避免 URL 传参(易泄露)。