HttpServletRequest 详解
HttpServletRequest 是 Java Servlet API 中处理 HTTP 请求的核心接口,它扩展了 ServletRequest 接口,提供了 HTTP 协议特有的功能。
一、HttpServletRequest 核心功能
1. 请求信息获取
-
基础信息:
String method = request.getMethod(); // GET/POST/PUT等 String protocol = request.getProtocol(); // HTTP/1.1 String scheme = request.getScheme(); // http/https String serverName = request.getServerName(); // 主机名 int serverPort = request.getServerPort(); // 端口号 String contextPath = request.getContextPath(); // 应用上下文路径 String servletPath = request.getServletPath(); // Servlet路径 String pathInfo = request.getPathInfo(); // 额外路径信息 -
URL 信息:
StringBuffer requestURL = request.getRequestURL(); // 完整URL String requestURI = request.getRequestURI(); // 去掉协议和主机的URI String queryString = request.getQueryString(); // 查询字符串
2. 请求头操作
// 获取单个请求头
String userAgent = request.getHeader("User-Agent");
// 获取所有请求头名
Enumeration<String> headerNames = request.getHeaderNames();
// 获取多个同名的请求头值
Enumeration<String> headers = request.getHeaders("Accept-Encoding");
// 获取日期型请求头
long date = request.getDateHeader("If-Modified-Since");
3. 请求参数获取
// 获取单个参数值
String username = request.getParameter("username");
// 获取多个同名参数值
String[] hobbies = request.getParameterValues("hobby");
// 获取所有参数名
Enumeration<String> paramNames = request.getParameterNames();
// 获取参数Map
Map<String, String[]> paramMap = request.getParameterMap();
4. 属性操作(请求作用域)
// 设置属性
request.setAttribute("currentUser", user);
// 获取属性
User user = (User) request.getAttribute("currentUser");
// 移除属性
request.removeAttribute("currentUser");
// 获取所有属性名
Enumeration<String> attrs = request.getAttributeNames();
二、高级功能
1. 会话管理
// 获取现有会话或创建新会话
HttpSession session = request.getSession();
// 只获取现有会话(不创建新会话)
HttpSession existingSession = request.getSession(false);
// 检查请求是否包含会话ID
boolean requestedSessionIdValid = request.isRequestedSessionIdValid();
2. Cookie 操作
// 获取所有Cookie
Cookie[] cookies = request.getCookies();
// 查找特定Cookie
Optional<Cookie> authCookie = Arrays.stream(request.getCookies())
.filter(c -> "authToken".equals(c.getName()))
.findFirst();
3. 多部分请求处理(文件上传)
if (ServletFileUpload.isMultipartContent(request)) {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
// 处理上传文件...
}
4. 请求分发
// 内部转发
RequestDispatcher dispatcher = request.getRequestDispatcher("/otherServlet");
dispatcher.forward(request, response);
// 包含其他资源
RequestDispatcher dispatcher = request.getRequestDispatcher("/header.jsp");
dispatcher.include(request, response);
三、实际应用示例
1. RESTful 参数处理
@WebServlet("/api/users/*")
public class UserApiServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
String pathInfo = req.getPathInfo(); // 如 "/123"
String[] parts = pathInfo.split("/");
if (parts.length > 1) {
String userId = parts[1]; // 获取ID
// 查询用户信息...
}
}
}
2. 请求日志拦截器
public class LoggingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
String requestInfo = String.format(
"%s %s from %s",
request.getMethod(),
request.getRequestURI(),
request.getRemoteAddr()
);
System.out.println("Request: " + requestInfo);
chain.doFilter(req, res);
}
}
3. 移动设备检测
public boolean isMobileDevice(HttpServletRequest request) {
String userAgent = request.getHeader("User-Agent");
String[] mobileKeywords = {
"Mobile", "Android", "iPhone", "iPad", "Windows Phone"
};
for (String keyword : mobileKeywords) {
if (userAgent.contains(keyword)) {
return true;
}
}
return false;
}
四、注意事项
-
参数编码:
// 在获取参数前设置编码 request.setCharacterEncoding("UTF-8"); -
输入流限制:
getInputStream()和getReader()只能调用一次- 调用后请求参数将不可用
-
线程安全:
- HttpServletRequest 对象只在当前请求线程中有效
- 不要尝试在多线程中共享请求对象
-
属性作用域:
- 请求属性只在当前请求范围内有效
- 转发后属性仍然可用,重定向后属性丢失
五、新特性(Servlet 3.0+)
1. 异步处理
AsyncContext asyncContext = request.startAsync();
asyncContext.start(() -> {
// 长时间处理
asyncContext.complete();
});
2. 文件上传简化
Part filePart = request.getPart("file");
String fileName = filePart.getSubmittedFileName();
filePart.write("/uploads/" + fileName);
18万+

被折叠的 条评论
为什么被折叠?



