由于 Java Web 开发有多种框架(如原生 Servlet、Spring、Spring MVC、Spring Boot),获取 Session 的方式也略有不同,下面我将分情况详细说明。

核心概念:什么是 Session?
- Session 是服务器端的一种技术,用于跟踪用户的整个会话。
- 当用户第一次访问服务器时,服务器会为该用户创建一个唯一的 Session ID,并将其发送给客户端(通常通过 Cookie 存储)。
- 在后续的请求中,客户端会自动携带这个 Session ID,服务器通过 ID 找到对应的 Session 对象,从而可以读取或写入用户的数据。
- Session 对象像一个“购物车”,可以存储任何 Java 对象(如
User对象、权限信息、购物车列表等)。
在原生 Servlet 中获取 Session 值
这是最基础的方式,理解了它,在其他框架中就能触类旁通。
步骤:
- 在
doGet或doPost方法中,通过HttpServletRequest对象获取HttpSession。 - 使用
session.getAttribute(String name)方法来根据键名获取存储的值,这个值是Object类型,需要强制类型转换。
示例代码:
设置 Session 值 (LoginServlet.java)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 模拟登录成功
String username = request.getParameter("username");
// 1. 获取Session对象(如果不存在,会自动创建一个新的)
HttpSession session = request.getSession();
// 2. 向Session中存储数据
session.setAttribute("username", username); // 存储String
session.setAttribute("userRole", "admin"); // 存储String
// 3. 也可以存储自定义对象
// User user = new User(username, "admin@example.com");
// session.setAttribute("user", user);
response.getWriter().println("Login successful! Session has been set.");
}
}
获取 Session 值 (ProfileServlet.java)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/profile")
public class ProfileServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取Session对象(如果会话不存在,返回null,而不会创建新会话)
HttpSession session = request.getSession(false);
response.setContentType("text/html;charset=UTF-8");
if (session != null && session.getAttribute("username") != null) {
// 2. 从Session中获取数据,注意类型转换
String username = (String) session.getAttribute("username");
String userRole = (String) session.getAttribute("userRole");
// 3. 获取自定义对象
// User user = (User) session.getAttribute("user");
response.getWriter().println("<h1>Welcome, " + username + "!</h1>");
response.getWriter().println("<p>Your role is: " + userRole + "</p>");
} else {
response.getWriter().println("You are not logged in. Please <a href='login.html'>login</a> first.");
}
}
}
关键点:

request.getSession(): 获取当前会话,如果不存在,则创建一个新的。request.getSession(false): 获取当前会话,如果不存在,则返回 null,不会创建新会话,常用于检查用户是否已登录。
在 Spring MVC 中获取 Session 值
Spring MVC 提供了更简洁、更强大的方式来处理 Session。
通过 HttpSession 参数注入(推荐)
可以直接在 Controller 方法的参数列表中添加 HttpSession 参数,Spring 会自动注入。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
@Controller
public class SessionController {
@PostMapping("/login")
@ResponseBody // 直接返回字符串,不跳转页面
public String login(@RequestParam String username, HttpSession session) {
// 直接使用session对象
session.setAttribute("username", username);
session.setAttribute("userRole", "user");
return "Login successful for user: " + username;
}
@GetMapping("/profile")
@ResponseBody
public String profile(HttpSession session) {
// 从session中获取值
String username = (String) session.getAttribute("username");
if (username != null) {
return "Welcome, " + username + "!";
} else {
return "Please login first.";
}
}
}
使用 @SessionAttributes 注解(用于模型数据共享)
这个注解用于将 Model 中的数据自动同步到 Session 中,当你希望某个数据不仅能在当前请求中访问,还能在后续请求中访问时使用它。
使用场景: 比如在表单分步提交时,将中间数据存入 Session。

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
// 1. 声明这个Controller中的哪些模型属性需要存入Session
// 这里的 "user" 是一个key,对应模型中的 user 对象
@SessionAttributes("user")
@Controller
public class UserProfileController {
// 2. 将数据添加到Model中
@GetMapping("/step1")
public String step1(Model model) {
model.addAttribute("user", new User()); // 假设User是一个POJO
return "step1"; // 返回一个视图名,step1.jsp
}
// 3. 在后续方法中,可以直接从Model中获取,它会自动从Session中读取
@GetMapping("/step2")
public String step2(@ModelAttribute("user") User user) {
// user 对象已经从Session中自动注入到这里了
// 你可以修改它,修改后的内容也会被写回Session
user.setEmail("updated@example.com");
return "step2";
}
}
注意: @SessionAttributes 不会自动管理 Session 的生命周期,通常需要配合 @SessionAttribute 来获取,或者手动管理 Session 的创建和销毁。
在 Spring Boot 中获取 Session 值
Spring Boot 是对 Spring MVC 的封装,所以方式与 Spring MVC 基本相同,但通常更推荐使用更现代的会话管理方式。
传统 HttpSession 方式(完全兼容 Spring MVC)
与 Spring MVC 中的方式一完全一样,直接注入 HttpSession 即可。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@RestController
public class SessionBootController {
@GetMapping("/set-session")
public String setSession(HttpSession session) {
session.setAttribute("message", "Hello from Spring Boot Session!");
return "Session has been set.";
}
@GetMapping("/get-session")
public String getSession(HttpSession session) {
String message = (String) session.getAttribute("message");
return message != null ? message : "No message found in session.";
}
}
使用 SessionManager(更现代的方式,推荐)
Spring Boot 2.4+ 引入了 SessionManager,它提供了一种更面向对象的方式来管理会话数据,可以避免直接操作 HttpSession,从而更容易进行测试和切换会话存储实现(如 Redis)。
你需要先创建一个配置类来暴露 SessionManager:
import org.springframework.context.annotation.Bean;
import org.springframework.session.Session;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.web.http.SessionRepositoryFilter;
import org.springframework.stereotype.Component;
@EnableSpringHttpSession // 启用 Spring Session
@Component
public class SessionConfig {
// 这个Bean的声明是必要的,用于让Spring Boot知道如何管理Session
@Bean
public SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter() {
// Spring Boot会自动配置,这里只是为了让编译通过
return null;
}
}
然后在 Controller 中使用 SessionManager:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
@RestController
public class ModernSessionController {
// 注入 SessionRepository
@Autowired
private SessionRepository<? extends Session> sessionRepository;
@GetMapping("/set-modern-session")
public String setModernSession(String sessionId) {
// 获取或创建一个会话
Session session = sessionRepository.createSession();
session.setAttribute("modernMessage", "This is a modern session approach!");
sessionRepository.save(session);
return "Modern session set for ID: " + session.getId();
}
@GetMapping("/get-modern-session")
public String getModernSession(String sessionId) {
Session session = sessionRepository.findById(sessionId);
if (session != null) {
String message = (String) session.getAttribute("modernMessage");
return message != null ? message : "No modern message found.";
}
return "Session not found.";
}
}
这种方式更灵活,但日常开发中,直接注入 HttpSession 仍然是最简单直接的方法。
移除 Session 值
除了获取和设置,移除 Session 值也很重要,尤其是在用户登出时。
-
移除单个属性:
session.removeAttribute("username"); -
销毁整个会话(使 Session 失效):
session.invalidate(); // 这会清空所有 Session 数据,并删除 Session ID
总结与最佳实践
| 场景 | 推荐方式 | 优点 |
|---|---|---|
| 原生 Servlet | request.getSession() 和 session.getAttribute() |
基础,必须掌握,是所有框架的原理。 |
| Spring MVC / Spring Boot | Controller 方法中直接注入 HttpSession |
简单、直观,是 Spring 生态中最常用的方式。 |
| Spring Boot (高级) | 使用 SessionRepository / SessionManager |
更灵活,易于测试,适合分布式会话(如配合 Redis)。 |
| Spring MVC (模型共享) | 使用 @SessionAttributes |
适用于需要在多个请求间共享 Model 数据的场景。 |
最佳实践建议:
- 最小化 Session 数据: Session 存储在服务器内存中,数据量大会增加服务器内存压力,影响性能。
- 存储简单数据: 最好只存储用户 ID、角色等标识性信息,而不是整个用户对象或大量数据,复杂对象可以从数据库中根据 ID 重新加载。
- 及时清理: 用户登出时,务必调用
session.invalidate()来销毁会话,防止会话固定攻击和资源浪费。 - 考虑分布式 Session: 在微服务或集群环境中,应使用 Spring Session + Redis 等方案,将 Session 数据集中存储,实现会话共享。
