本文目录导读:

我来详细说明Java中实现Session存储的几种常见方式。
基本Session存储(HttpSession)
使用Servlet API的HttpSession
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SessionServlet extends HttpServlet {
// 存储数据到Session
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 获取Session(如果没有则创建)
HttpSession session = request.getSession();
// 设置Session过期时间(秒),默认30分钟
session.setMaxInactiveInterval(3600); // 1小时
// 存储数据
session.setAttribute("username", "张三");
session.setAttribute("userRole", "admin");
// 存储对象
User user = new User("张三", "zhangsan@example.com");
session.setAttribute("user", user);
response.getWriter().println("Session存储成功!");
}
// 读取Session数据
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
HttpSession session = request.getSession(false);
if (session != null) {
String username = (String) session.getAttribute("username");
User user = (User) session.getAttribute("user");
response.getWriter().println("用户名: " + username);
response.getWriter().println("用户信息: " + user);
} else {
response.getWriter().println("Session不存在或已过期");
}
}
}
Redis存储Session(分布式场景)
添加依赖(Maven)
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) // 30分钟
public class RedisSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("SESSIONID");
serializer.setCookiePath("/");
serializer.setDomainName("example.com");
serializer.setUseHttpOnlyCookie(true);
serializer.setUseSecureCookie(false);
return serializer;
}
}
使用Redis存储Session
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/session")
public class SessionController {
@PostMapping("/save")
public String saveSession(HttpSession session) {
// 存储到Redis
session.setAttribute("userId", "12345");
session.setAttribute("loginTime", System.currentTimeMillis());
session.setAttribute("userInfo", new UserInfo("张三", "admin"));
return "Session已保存到Redis,Session ID: " + session.getId();
}
@GetMapping("/get")
public Object getSession(HttpSession session) {
String userId = (String) session.getAttribute("userId");
Long loginTime = (Long) session.getAttribute("loginTime");
UserInfo userInfo = (UserInfo) session.getAttribute("userInfo");
return String.format("用户ID: %s, 登录时间: %d, 用户信息: %s",
userId, loginTime, userInfo);
}
@PostMapping("/clear")
public String clearSession(HttpSession session) {
session.invalidate(); // 销毁Session
return "Session已清除";
}
}
// 用户信息类(必须实现序列化)
class UserInfo implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String role;
public UserInfo(String name, String role) {
this.name = name;
this.role = role;
}
// getters and setters
}
数据库存储Session
创建Session表
CREATE TABLE user_sessions (
session_id VARCHAR(100) PRIMARY KEY,
user_id VARCHAR(50),
session_data BLOB,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_access_time TIMESTAMP,
expiry_time TIMESTAMP
);
JDBC Session实现
import java.sql.*;
import java.util.Date;
public class DatabaseSessionManager {
private Connection connection;
public DatabaseSessionManager(Connection connection) {
this.connection = connection;
}
// 保存Session
public void saveSession(Session session) throws SQLException {
String sql = "INSERT INTO user_sessions (session_id, user_id, session_data, last_access_time, expiry_time) " +
"VALUES (?, ?, ?, ?, ?) " +
"ON DUPLICATE KEY UPDATE session_data = ?, last_access_time = ?, expiry_time = ?";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setString(1, session.getId());
pstmt.setString(2, session.getUserId());
pstmt.setObject(3, serialize(session.getData()));
pstmt.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
pstmt.setTimestamp(5, new Timestamp(session.getExpiryTime().getTime()));
pstmt.setObject(6, serialize(session.getData()));
pstmt.setTimestamp(7, new Timestamp(System.currentTimeMillis()));
pstmt.setTimestamp(8, new Timestamp(session.getExpiryTime().getTime()));
pstmt.executeUpdate();
}
}
// 读取Session
public Session getSession(String sessionId) throws SQLException {
String sql = "SELECT * FROM user_sessions WHERE session_id = ? AND expiry_time > NOW()";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setString(1, sessionId);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
Session session = new Session();
session.setId(rs.getString("session_id"));
session.setUserId(rs.getString("user_id"));
session.setData(deserialize(rs.getBlob("session_data")));
session.setLastAccessTime(rs.getTimestamp("last_access_time"));
session.setExpiryTime(rs.getTimestamp("expiry_time"));
return session;
}
}
return null;
}
// 删除过期Session
public void cleanExpiredSessions() throws SQLException {
String sql = "DELETE FROM user_sessions WHERE expiry_time < NOW()";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
int deleted = pstmt.executeUpdate();
System.out.println("清理了 " + deleted + " 个过期Session");
}
}
// 序列化方法
private byte[] serialize(Object obj) {
// 实现对象序列化逻辑
return new byte[0];
}
private Object deserialize(Blob blob) {
// 实现对象反序列化逻辑
return null;
}
}
// Session实体类
class Session {
private String id;
private String userId;
private Object data;
private Date lastAccessTime;
private Date expiryTime;
// getters and setters
}
最佳实践建议
Session配置优化
// application.yml配置
spring:
session:
store-type: redis # 可选:redis, jdbc, hazelcast
timeout: 1800 # Session超时时间(秒)
redis:
namespace: myapp:session # Redis key前缀
flush-mode: on-save # 保存策略:immediate/on-save
Session工具类
import javax.servlet.http.HttpSession;
import java.util.Optional;
public class SessionUtil {
// 安全获取Session属性
public static <T> T getAttribute(HttpSession session, String key, Class<T> type) {
return Optional.ofNullable(session)
.map(s -> s.getAttribute(key))
.filter(type::isInstance)
.map(type::cast)
.orElse(null);
}
// 带默认值的获取
public static <T> T getAttributeOrDefault(HttpSession session, String key,
Class<T> type, T defaultValue) {
T value = getAttribute(session, key, type);
return value != null ? value : defaultValue;
}
// 批量添加属性
public static void addAttributes(HttpSession session, java.util.Map<String, Object> attributes) {
if (session != null && attributes != null) {
attributes.forEach(session::setAttribute);
}
}
}
注意事项
- 序列化要求:存储的对象必须实现
Serializable接口 - 性能考虑:避免存储大数据对象(如大图片)
- 安全问题:敏感信息加密存储
- 过期策略:合理设置Session超时时间
- 分布式环境:使用Redis等集中式存储方案
选择合适的Session存储方式取决于你的应用场景:
- 单机应用:使用默认的HttpSession
- 分布式应用:推荐使用Redis
- 需要持久化:使用数据库存储