Spring Boot集群环境下用MapSessionRepository替代Redis实现非持久化Session
Spring Boot 2.6.3集群环境下非持久化会话存储及FindByIndexNameSessionRepository实现问题
需求背景
- 需要在Spring Boot中存储高容量用户会话数据
- 尝试过Redis存储方案,但集群环境下无法正常工作
- 目标:实现集群环境下的非持久化会话存储,希望能提供示例代码
问题详情
在Spring Boot 2.6.3中尝试实现FindByIndexNameSessionRepository时,遇到以下依赖注入错误:
Description: Field sessions in com.teknospire.switch_transaction.controller.login.Login required a bean of type 'org.springframework.session.FindByIndexNameSessionRepository' that could not be found. The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true) Action: Consider defining a bean of type 'org.springframework.session.FindByIndexNameSessionRepository' in your configuration.
当前使用的配置代码:
@EnableSpringHttpSession @Configuration public class SpringHttpSessionConfig { @Bean public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter( SessionRepository<S> sessionRepository, ServletContext servletContext) { SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(sessionRepository); sessionRepositoryFilter.setServletContext(servletContext); return sessionRepositoryFilter; } @Bean public MapSessionRepository sessionRepository() { return new MapSessionRepository(new ConcurrentHashMap<>()); } }
问题原因
你使用的MapSessionRepository仅实现了SessionRepository接口,并未实现FindByIndexNameSessionRepository,因此Spring容器无法找到对应类型的Bean,导致注入失败。
解决方案
方案1:自定义内存会话仓库(单节点)
如果仅需要单节点的非持久化会话存储,可以自定义一个同时实现两个接口的会话仓库:
自定义会话仓库类
import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.session.MapSession; import org.springframework.session.Session; import org.springframework.session.SessionRepository; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class InMemorySessionRepository implements SessionRepository<MapSession>, FindByIndexNameSessionRepository<MapSession> { private final Map<String, MapSession> sessions = new ConcurrentHashMap<>(); @Override public MapSession createSession() { MapSession session = new MapSession(); sessions.put(session.getId(), session); return session; } @Override public void save(MapSession session) { sessions.put(session.getId(), new MapSession(session)); } @Override public MapSession findById(String id) { MapSession session = sessions.get(id); return session != null ? new MapSession(session) : null; } @Override public void deleteById(String id) { sessions.remove(id); } @Override public Map<String, MapSession> findByIndexNameAndIndexValue(String indexName, String indexValue) { if (!PRINCIPAL_NAME_INDEX_NAME.equals(indexName)) { return Collections.emptyMap(); } return sessions.values().stream() .filter(session -> indexValue.equals(session.getAttribute(PRINCIPAL_NAME_INDEX_NAME))) .collect(Collectors.toMap(Session::getId, session -> new MapSession(session))); } }
修改配置类
删除手动注册SessionRepositoryFilter的代码(Spring Boot会自动配置),并返回自定义的会话仓库Bean:
@EnableSpringHttpSession @Configuration public class SpringHttpSessionConfig { @Bean public FindByIndexNameSessionRepository<MapSession> sessionRepository() { return new InMemorySessionRepository(); } }
方案2:使用Hazelcast实现集群非持久化会话存储
如果需要集群环境下共享会话数据,推荐使用Hazelcast作为分布式内存存储(默认非持久化,重启后数据丢失),Spring Session原生支持Hazelcast:
添加依赖
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-hazelcast</artifactId> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast</artifactId> </dependency>
配置类
@EnableSpringHttpSession @Configuration public class HazelcastSessionConfig { @Bean public com.hazelcast.core.HazelcastInstance hazelcastInstance() { com.hazelcast.config.Config config = new com.hazelcast.config.Config(); // 本地测试启用多播自动发现,生产环境需配置TCP/IP集群地址 config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(true); return com.hazelcast.core.Hazelcast.newHazelcastInstance(config); } @Bean public FindByIndexNameSessionRepository<Session> sessionRepository(com.hazelcast.core.HazelcastInstance hazelcastInstance) { return new org.springframework.session.hazelcast.HazelcastIndexedSessionRepository(hazelcastInstance); } }
示例代码说明
上述两种方案的核心代码可直接集成到项目中:
- 方案1适合单节点测试或非集群场景
- 方案2适合集群环境,无需额外持久化存储,会话数据在集群节点间自动同步
内容的提问来源于stack exchange,提问作者Pramod Kumar
相关产品推荐
相关产品推荐

