springboot+spring-session

1. 实现背景

      测试环境上部署了一个单机项目,项目的context-path为空,之后再经过nginx的转发进行部署,项目可以正常进行登录等等一系列操作;生产环境跟测试环境代码完全相同,只是相关的项目配置包括nginx配置不同,项目可以正常启动,但登录失败。原本以为是nginx相关的配置有问题,导致调完登录接口,返回的cookie中携带的项目名不一致导致的。经过检查发现登录接口返回的cookie中跟后续请求的cookie中的参数一致,所以跟配置无关。最后发现生产配置的项目是集群模式,所以根本还是出现在session共享上面。

2.具体实现

   这里做的共享session用的是redis,所以要安装redis并引入相关依赖;

<!--session-->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
<!-- redis依赖配置 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

   其次application.yml中添加相关配置

spring:
   session:
      store-type: redis #是否将session存到redis  none/redis
      timeout: 1800 # 配置session在redis中的过期时间
      redis:
      flush-mode: immediate #保存时刷新,即响应结束后刷新。默认是 on_save;immediate实时刷新
      namespace: smith:session #默认是spring:session
   redis:
      host: 127.0.0.1 # Redis服务器地址
      database: 0 # Redis数据库索引(默认为0)
      port: 6379 # Redis服务器连接端口
      password: # Redis服务器连接密码(默认为空)
      timeout: 3000ms # 连接超时时间

    到这里配置工作就完成了,启动项目即可。

3. 错误信息

 org.springframework.boot.autoconfigure.session.SessionRepositoryUnavailableException: No session repository could be auto-configured, check your configuration (session store type is 'redis')

    因为当store-type配置为redis的时候,redis是需要序列化的,所以我们还需要对restTemplate进行序列化,至此问题解决,项目可成功启动。

@Configuration
public class RedisConfiguration {
    /**
     * @param redisConnectionFactory:配置不同的客户端,这里注入的redis连接工厂不同: JedisConnectionFactory、LettuceConnectionFactory
     * @功能描述 :配置Redis序列化,原因如下:
     * (1) StringRedisTemplate的序列化方式为字符串序列化,
     * RedisTemplate的序列化方式默为jdk序列化(实现Serializable接口)
     * (2) RedisTemplate的jdk序列化方式在Redis的客户端中为乱码,不方便查看,
     * 因此一般修改RedisTemplate的序列化为方式为JSON方式【建议使用GenericJackson2JsonRedisSerializer】
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // key采用String的序列化方式
        redisTemplate.setKeySerializer(StringRedisSerializer.UTF_8);
        // value序列化方式采用jackson
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(StringRedisSerializer.UTF_8);
        //hash的value序列化方式采用jackson
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}

 4. 总结

    当集群模式时候,需要将登录相关信息储存在redis或其他数据库中实现共享,也就是说sessionid保存在客户端的cookie里面,然后将该sessionid作为key将session保存在redis服务端。当部署很多个项目时候,因为session-namespace是默认值,所以可以修改namespace的值,把不同项目区分开。

posted @ 2022-12-04 15:12  写字楼间写字员  阅读(189)  评论(0编辑  收藏  举报