You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:41:18