Servlet 中 Request、Response 和 Session 的详细介绍
在 Java Web 开发中,ServletRequest、ServletResponse 和 HttpSession 是三个核心对象,它们分别负责处理客户端请求、服务器响应以及用户会话管理。下面对这三个对象进行详细介绍。
一、ServletRequest/HttpServletRequest
ServletRequest 是一个接口,代表客户端的请求信息,而 HttpServletRequest 是它的子接口,专门用于 HTTP 协议的请求。
1. 主要功能
- 获取请求的基本信息(如 URL、URI、请求方法等)
- 获取请求参数(表单数据、URL 参数等)
- 获取请求头信息
- 获取客户端信息
- 在请求作用域中存储和获取属性
- 获取请求的输入流
2. 常用方法
2.1 获取请求基本信息
// 获取请求方法(GET、POST 等)
String method = request.getMethod();
// 获取请求的 URI(不包含协议、主机名和端口)
String uri = request.getRequestURI();
// 获取完整的请求 URL
StringBuffer url = request.getRequestURL();
// 获取上下文路径(项目的虚拟路径)
String contextPath = request.getContextPath();
// 获取请求路径(不包含上下文路径)
String servletPath = request.getServletPath();
2.2 获取请求参数
// 获取单个参数值
String username = request.getParameter("username");
// 获取多个参数值(如复选框)
String[] hobbies = request.getParameterValues("hobby");
// 获取所有参数名
Enumeration<String> paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
String paramValue = request.getParameter(paramName);
// 处理参数...
}
// 获取所有参数的 Map
Map<String, String[]> paramMap = request.getParameterMap();
2.3 获取请求头信息
// 获取单个请求头值
String userAgent = request.getHeader("User-Agent");
// 获取所有请求头名称
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
// 处理请求头...
}
2.4 获取客户端信息
// 获取客户端 IP 地址
String clientIp = request.getRemoteAddr();
// 获取客户端端口号
int clientPort = request.getRemotePort();
2.5 请求属性操作
// 设置请求属性(可在请求转发时传递数据)
request.setAttribute("userInfo", userInfo);
// 获取请求属性
UserInfo userInfo = (UserInfo) request.getAttribute("userInfo");
2.6 请求转发
// 获取请求转发器
RequestDispatcher dispatcher = request.getRequestDispatcher("/targetServlet");
// 执行转发(同一个请求)
dispatcher.forward(request, response);
二、ServletResponse/HttpServletResponse
ServletResponse 是一个接口,代表服务器对客户端的响应,而 HttpServletResponse 是它的子接口,专门用于 HTTP 协议的响应。
1. 主要功能
- 设置响应状态码
- 设置响应头
- 向客户端输出数据
- 实现请求重定向
- 设置内容类型和编码格式
2. 常用方法
2.1 设置响应内容
// 获取字符输出流
PrintWriter writer = response.getWriter();
// 输出内容到客户端
writer.write("Hello, World!");
writer.println("<h1>Welcome</h1>");
writer.flush();
writer.close();
// 获取字节输出流(用于二进制数据,如图片、文件等)
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write("Hello, World!".getBytes());
outputStream.flush();
outputStream.close();
2.2 设置内容类型和编码
// 设置内容类型和编码格式(解决中文乱码问题)
response.setContentType("text/html;charset=utf-8");
// 仅设置响应的字符编码
response.setCharacterEncoding("utf-8");
// 设置响应的内容类型为 JSON
response.setContentType("application/json;charset=utf-8");
2.3 请求重定向
// 重定向到其他资源(客户端跳转,会发送新的请求)
response.sendRedirect("/login");
// 或者重定向到完整 URL
response.sendRedirect("https://www.example.com");
2.4 设置响应头
// 设置单个响应头
response.setHeader("Refresh", "3;url=/index"); // 3秒后刷新并跳转到/index
// 添加响应头
response.addHeader("Cache-Control", "no-cache");
// 设置内容长度
response.setContentLength(1024);
// 设置文件下载响应头
response.setHeader("Content-Disposition", "attachment;filename=example.zip");
2.5 设置状态码
// 设置 HTTP 状态码
response.setStatus(404); // 未找到资源
response.setStatus(302); // 临时重定向
// 发送错误状态码及错误信息
response.sendError(403, "Forbidden: You don't have permission");
三、HttpSession
HttpSession 是一个接口,代表客户端与服务器之间的会话。会话是指一个用户从第一次访问服务器开始,到最后一次访问服务器结束的整个过程。
1. 主要功能
- 在多次请求之间保存用户状态和数据
- 识别同一客户端的多次请求
- 存储用户登录信息和临时数据
2. 常用方法
2.1 获取 Session 对象
// 获取当前请求的会话,如果没有则创建新会话
HttpSession session = request.getSession();
// 获取当前请求的会话,如果没有则返回 null
HttpSession session = request.getSession(false);
2.2 Session 属性操作
// 设置 Session 属性
User user = new User("admin", "admin@example.com");
session.setAttribute("user", user);
// 获取 Session 属性
User currentUser = (User) session.getAttribute("user");
// 移除 Session 属性
session.removeAttribute("user");
// 获取所有 Session 属性名
Enumeration<String> attributeNames = session.getAttributeNames();
while(attributeNames.hasMoreElements()) {
String attributeName = attributeNames.nextElement();
Object attributeValue = session.getAttribute(attributeName);
// 处理属性...
}
2.3 Session 生命周期管理
// 获取 Session 创建时间(毫秒时间戳)
long creationTime = session.getCreationTime();
// 获取最后一次访问时间
long lastAccessedTime = session.getLastAccessedTime();
// 获取 Session ID
String sessionId = session.getId();
// 检查 Session 是否为新创建的
boolean isNew = session.isNew();
// 设置 Session 最大不活动时间(秒)
session.setMaxInactiveInterval(3600); // 1小时
// 立即使 Session 失效
session.invalidate();
四、Request、Response 和 Session 的作用域比较
| 对象 | 作用域 | 生命周期 | 特点 |
|---|---|---|---|
| Request | 请求作用域 | 一次请求(从客户端发送请求到服务器返回响应) | 数据只能在本次请求内共享,常用于请求转发时传递数据 |
| Session | 会话作用域 | 一次会话(从用户首次访问到会话超时或注销) | 数据可以在同一个用户的多次请求之间共享,常用于保存用户登录状态 |
| ServletContext | 应用作用域 | 整个应用程序(从服务器启动到服务器关闭) | 数据可以在整个应用程序的所有用户之间共享,常用于保存全局配置信息 |
五、使用示例
1. 表单处理与会话管理
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置请求编码
request.setCharacterEncoding("UTF-8");
// 获取表单参数
String username = request.getParameter("username");
String password = request.getParameter("password");
// 验证用户(实际应用中应查询数据库)
if ("admin".equals(username) && "123456".equals(password)) {
// 登录成功,创建用户对象并保存到 Session
User user = new User(username, "admin@example.com");
HttpSession session = request.getSession();
session.setAttribute("user", user);
// 设置会话超时时间为30分钟
session.setMaxInactiveInterval(1800);
// 重定向到首页
response.sendRedirect("/home");
} else {
// 登录失败,设置错误信息并转发回登录页面
request.setAttribute("error", "用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}
2. 中文输出示例
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应内容类型和编码,解决中文乱码
response.setContentType("text/html;charset=utf-8");
// 获取输出流
PrintWriter out = response.getWriter();
// 输出中文内容
out.println("<html>");
out.println("<head><title>中文示例</title></head>");
out.println("<body>");
out.println("<h1>你好,世界!</h1>");
// 从会话中获取用户信息(如果存在)
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("user") != null) {
User user = (User) session.getAttribute("user");
out.println("<p>欢迎回来," + user.getUsername() + "!</p>");
}
out.println("</body>");
out.println("</html>");
}
}
六、注意事项
-
编码问题:在处理表单数据或输出中文内容时,务必设置正确的编码格式,避免中文乱码。
-
Session 管理:合理设置 Session 超时时间,避免资源浪费;对于敏感操作,验证 Session 是否存在有效用户。
-
请求转发与重定向:
- 请求转发(forward)是服务器内部跳转,地址栏不变,只发送一次请求
- 重定向(redirect)是客户端跳转,地址栏改变,发送两次请求
-
资源释放:使用输出流(如 PrintWriter、ServletOutputStream)后应及时关闭,避免资源泄漏。
-
属性作用域:根据数据共享范围的需求,选择合适的作用域(request、session、servletContext)来存储数据。
通过合理使用 Request、Response 和 Session 对象,我们可以构建功能完善的 Web 应用程序,实现用户交互、数据处理和状态管理等核心功能。