编程自学指南:java程序设计开发,会话管理进阶(分布式 Session/Token)
一、课程信息
学习目标
- 理解分布式系统中会话管理的核心挑战
- 掌握 3 种分布式 Session 解决方案的原理与实现
- 掌握 JWT Token 的工作流程与实战应用
- 能根据场景选择合适的会话管理方案
二、课程导入:单体 vs 分布式
🌰 场景对比
环境 | 会话管理方式 | 问题点 |
---|---|---|
单体应用 | 本地 Session | 无(单服务器) |
分布式集群 | 本地 Session | 服务器 A 的 Session 无法在服务器 B 访问 |
三、分布式 Session 核心问题
🔍 1. 问题根源
- 服务器无状态性:HTTP 协议本身不保存状态
- 负载均衡:请求可能被分发到不同服务器,导致 Session 丢失
🔍 2. 典型场景
graph LR
User -->|请求1| ServerA[服务器A]
User -->|请求2| ServerB[服务器B]
ServerA --> SessionA[Session@A]
ServerB --> SessionB[Session@B]
问题:请求 1 在 A 服务器创建的 Session,请求 2 到 B 服务器时无法访问
四、分布式 Session 解决方案
🔥 方案 1:粘性会话(Sticky Session)
原理
通过负载均衡器将同一个用户的所有请求路由到同一台服务器
实现(Tomcat)
- 修改负载均衡配置(如 Nginx):
upstream tomcat_cluster { ip_hash; # 基于 IP 哈希实现粘性 server 192.168.1.10:8080; server 192.168.1.11:8080; }
- 验证:
@WebServlet("/session") public class SessionServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) { HttpSession session = req.getSession(); session.setAttribute("server", req.getLocalAddr()); resp.getWriter().write("当前服务器:" + session.getAttribute("server")); } }
🔥 方案 2:Session 复制
原理
多台服务器之间同步 Session 数据
实现(Tomcat 集群)
- 配置
server.xml
:<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
- 验证:
在 ServerA 创建 Session,ServerB 可读取相同数据
🔥 方案 3:Session 共享(集中存储)
原理
将 Session 统一存储到第三方存储(如 Redis)
实现(Redis + Spring Session)
- 添加依赖:
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
- 配置 Redis:
@Configuration @EnableRedisHttpSession public class SessionConfig { @Bean public RedisConnectionFactory connectionFactory() { return new JedisConnectionFactory(); } }
五、Token 会话管理(JWT 详解)
🔍 1. JWT 核心概念
- 定义:
JWT(JSON Web Token)是无状态的会话管理方式,通过签名的 JSON 字符串在客户端与服务器间传递状态 - 结构:
Header.payload.Signature
🔥 2. JWT 工作流程
sequenceDiagram
User->>Server: 提交用户名/密码
Server->>Server: 验证通过
Server->>User: 返回 JWT Token
User->>Server: 携带 Token 请求资源
Server->>Server: 验证 Token 有效性
Server->>User: 返回资源
🔥 3. 实战案例:基于 JWT 的登录
① 生成 Token(LoginServlet)
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
if ("admin".equals(username) && "123".equals(password)) {
// 生成 JWT(使用 jjwt 库)
String token = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + 30*60*1000)) // 30分钟过期
.signWith(SignatureAlgorithm.HS256, "secretKey")
.compact();
resp.setContentType("application/json");
resp.getWriter().write("{\"token\":\"" + token + "\"}");
}
}
}
② 验证 Token(Filter)
@WebFilter("/api/*")
public class JwtFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
String token = ((HttpServletRequest) req).getHeader("Authorization");
try {
Jwts.parser().setSigningKey("secretKey").parseClaimsJws(token);
chain.doFilter(req, res);
} catch (Exception e) {
((HttpServletResponse) res).sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
六、分布式 Session vs Token 对比
特性 | 分布式 Session | Token |
---|---|---|
状态存储 | 服务器端(Redis/DB) | 客户端(Cookie/Header) |
扩展性 | 好(集中存储) | 极好(无状态) |
安全性 | 高(数据在服务器) | 中(需防 Token 泄露) |
典型场景 | 传统 Web 应用集群 | 前后端分离、微服务 |
七、关联知识:Token 与前后端分离
🔗 1. 前端存储 Token
// 登录成功后存储 Token
localStorage.setItem('token', response.data.token);
// 每次请求携带 Token
fetch('/api/data', {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('token')
}
});
🔗 2. 与 Spring MVC 的集成
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/user")
public User getUser(HttpServletRequest request) {
String username = Jwts.parser()
.setSigningKey("secretKey")
.parseClaimsJws(request.getHeader("Authorization"))
.getBody().getSubject();
return userService.getUser(username);
}
}
八、课堂练习
练习 1:粘性会话配置
任务:
- 使用 Nginx 配置两个 Tomcat 实例的粘性会话
- 验证同一用户的请求是否路由到同一台服务器
练习 2:JWT 过期处理
任务:
- 修改 JWT 有效期为 1 分钟
- 编写 Filter 在 Token 过期时返回 401 状态码
九、课程总结
知识图谱:
分布式会话管理
↳ 三大方案:
✅ 粘性会话(简单易用,单点故障)
✅ Session 复制(数据同步,性能开销大)
✅ 集中存储(Redis/DB,推荐方案)
↳ Token 方案:
✅ JWT 原理与实战
✅ 前后端分离场景应用
口诀记忆:
“分布式会话有三招,粘性复制集中存,
Token 无状态效率高,前后分离离不了,
方案选择看场景,安全扩展要权衡!”
十、课后作业
必做 1:分布式 Session 集群
要求:
- 搭建两个 Tomcat 实例,使用 Redis 共享 Session
- 实现用户在任一节点登录后,其他节点可访问其 Session
必做 2:JWT 权限管理
任务:
- 在 JWT 中添加角色信息(如 admin/user)
- 在 Filter 中根据角色控制访问权限
- admin 可访问
/api/admin
- user 禁止访问
- admin 可访问