核心概念
要理解 Session 是什么:

- Session 是服务器端的一种机制,用于在多个 HTTP 请求之间保持用户的状态信息。
- 服务器会为每个用户创建一个唯一的 Session ID,并通过 Cookie 发送给客户端,后续请求客户端会携带这个 ID,服务器通过 ID 找到对应的 Session 对象。
HttpSession是 Java Servlet API 中表示 Session 的接口。
“清空 Session” 的本质就是销毁这个 HttpSession 对象,使其在服务器端不再可用。
原生 Servlet API (最基础)
如果你没有使用任何高级框架(如 Spring, Spring MVC),而是直接使用 Servlet,操作非常直接。
使用 invalidate() (最彻底、最常用)
session.invalidate() 方法会立即销毁当前的 Session 对象,并释放所有与之绑定的资源,这是“清空 Session”最标准、最推荐的方式。
示例代码:
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("/logout") // 访问这个URL就会退出登录
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取当前的 HttpSession 对象
HttpSession session = request.getSession(false); // 使用 false 参数,session 不存在则返回 null,避免创建新 session
// 2. 检查 session 是否存在
if (session != null) {
// 3. 调用 invalidate() 方法销毁 session
session.invalidate();
System.out.println("Session has been invalidated.");
}
// 4. 重定向到登录页面
response.sendRedirect(request.getContextPath() + "/login.html");
}
}
代码解释:
request.getSession(false): 获取 Session,传入false是一个好习惯,表示“如果不存在就别新建,直接返回 null”,这可以避免在登出逻辑中意外创建一个新的 Session。session.invalidate(): 核心方法,彻底销毁 Session。response.sendRedirect(...): 销毁 Session 后,通常会将用户重定向到登录页面或其他页面。
手动移除所有属性 (不推荐)
你也可以遍历 Session 中的所有属性,并手动移除它们,这种方式并没有真正销毁 Session 对象,它只是一个空壳,服务器端的会话依然存在,会占用内存,直到超时。
示例代码 (不推荐):
HttpSession session = request.getSession();
java.util.Enumeration<String> attributeNames = session.getAttributeNames();
while (attributeNames.hasMoreElements()) {
String attributeName = attributeNames.nextElement();
session.removeAttribute(attributeName);
}
// session 对象本身还存在,只是是空的
为什么不推荐?
- 不彻底:Session 对象本身未被销毁,仍然占用服务器资源。
- 代码冗余:
invalidate()一行代码就能搞定,而这种方式需要写循环。 - 可能遗漏:Session 中存储了非标准的属性,可能会被遗漏。
Spring / Spring MVC
在 Spring MVC 中,你通常不会直接操作 HttpSession 对象,而是通过注入 HttpSession 或使用 Spring 提供的更高级的抽象。
直接注入 HttpSession 并调用 invalidate()
这是最直接的方式,与原生 Servlet API 几乎一样。
示例代码 (Controller 中):
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpSession;
@Controller
public class LogoutController {
@GetMapping("/logout")
public String logout(HttpSession session) {
// 检查 session 是否存在 (Spring MVC 会自动管理,通常不为 null)
if (session != null) {
session.invalidate();
System.out.println("Session invalidated in Spring MVC.");
}
return "redirect:/login"; // 重定向到登录页面
}
}
使用 Spring Security (推荐)
如果你的项目使用了 Spring Security,它提供了更优雅、更安全的退出登录机制,Spring Security 会自动处理 Session 失效、Cookie 清除等所有事情。
示例代码 (Spring Security 配置):
你只需要在配置类中添加一个退出登录的 URL 映射即可。
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// ... 其他配置,如登录、角色等
.logout()
.logoutUrl("/logout") // 设置退出登录的URL
.logoutSuccessUrl("/login?logout") // 退出成功后跳转的URL
.invalidateHttpSession(true) // 使HTTP session失效 (默认为true)
.deleteCookies("JSESSIONID"); // 删除与 session 相关的 cookie (默认会删除)
}
}
访问方式:
用户只需访问 /logout 这个 URL,Spring Security 就会自动处理所有事情,包括:
- 使当前 Session 失效。
- 清除
JSESSIONIDCookie。 - 清除 Security 上下文中的认证信息。
- 重定向到
/login?logout页面。
这是生产环境中最推荐的方式,因为它最安全、最全面。
Java EE (Jakarta EE) / Jakarta Servlet
从 Java 9 开始,Java EE 的包名从 javax.* 迁移到了 jakarta.*,如果你使用的是较新版本的 Jakarta EE (在 Jakarta EE 8 / 9+ 项目中),代码需要更换包名。
原生 Servlet API (Jakarta EE 版本):
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
response.sendRedirect(request.getContextPath() + "/login.html");
}
}
主要变化:
javax.servlet.*->jakarta.servlet.*javax.servlet.http.*->jakarta.servlet.http.*
总结与最佳实践
| 场景 | 推荐方法 | 优点 |
|---|---|---|
| 原生 Servlet / Jakarta Servlet | session.invalidate() |
标准做法,彻底、简单。 |
| Spring MVC | session.invalidate() 或注入 HttpSession 后调用 |
直接有效,与底层 API 一致。 |
| 使用 Spring Security | 配置 .logout() |
强烈推荐,一站式解决方案,自动处理 Session、Cookie、安全上下文,更安全、更全面。 |
核心要点:
- 首选
invalidate():在绝大多数情况下,调用session.invalidate()是清空 Session 的最佳方式。 - 框架优先:如果使用了 Spring Security 等安全框架,优先使用框架提供的退出功能,不要自己手动处理。
- 注意包名:在新项目中,注意使用
jakarta.*包名,而不是已过时的javax.*。
