zoukankan      html  css  js  c++  java
  • Spring boot集成Redis实现sessions共享时,sessions过期时间问题分析

        Springboot鼓励零配置的方式,帮你做好大部分重复劳动的事,好到不能再好;具体的Redis安装方法和Springboot集成Redis方法,可以去搜索相关文章或参考该文章http://www.cnblogs.com/mengmeng89012/p/5519698.html。

    当做用户权限管理时,一般都设置一个session过期时间,以确保用户长时间不操作时自动退出系统。

    Spring seesions的原理可以参考该文章:http://blog.csdn.net/wojiaolinaaa/article/details/62424642

    在springboot中设置該值的方法如下:

    1.  
      @Configuration
    2.  
      @EnableRedisHttpSession(maxInactiveIntervalInSeconds= 3600,redisNamespace = "tl")
    3.  
      public class RedisSessionConfig {
    4.  
       
    5.  
      }

    即开启Redis共享sessions的配置类的注解设置maxInactiveIntervalInSeconds的值,单位为秒,默认值为1800秒;问题来了,当设置其为600秒时,在redis的客户端查看sessions的key的过期时间时(redis命令:ttl key,查看其有效时间),发现該值为1100秒;有问题有疑惑找源码,集成redis的代码在spring-sessions包中,找到

    org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession注解,该注解的解析类为:
    org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;可以看到
    maxInactiveIntervalInSeconds默认值为1800秒,找到setImportMetadata函数:
    
    
    1.  
      public void setImportMetadata(AnnotationMetadata importMetadata) {
    2.  
       
    3.  
      Map<String, Object> enableAttrMap = importMetadata
    4.  
      .getAnnotationAttributes(EnableRedisHttpSession.class.getName());
    5.  
      AnnotationAttributes enableAttrs = AnnotationAttributes.fromMap(enableAttrMap);
    6.  
      /**
    7.  
      *解析注解,获取maxInactiveIntervalInSeconds赋值给配置类的maxInactiveIntervalInSeconds对象
    8.  
      */
    9.  
      this.maxInactiveIntervalInSeconds = enableAttrs
    10.  
      .getNumber("maxInactiveIntervalInSeconds");
    11.  
      String redisNamespaceValue = enableAttrs.getString("redisNamespace");
    12.  
      /**
    13.  
      *设置命名空间
    14.  
      */
    15.  
      if (StringUtils.hasText(redisNamespaceValue)) {
    16.  
      this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue);
    17.  
      }
    18.  
      this.redisFlushMode = enableAttrs.getEnum("redisFlushMode");
    19.  
      }
    	利用Redis作为sessions共享仓实现类为org.springframework.session.data.redis.RedisOperationsSessionRepository
    其执行session过期策略的实现类为RedisSessionExpirationPolicy,其过期的具体函数如下:
    1.  
      public void onExpirationUpdated(Long originalExpirationTimeInMilli,
    2.  
      ExpiringSession session) {
    3.  
      String keyToExpire = "expires:" + session.getId();
    4.  
      long toExpire = roundUpToNextMinute(expiresInMillis(session));
    5.  
       
    6.  
      if (originalExpirationTimeInMilli != null) {
    7.  
      long originalRoundedUp = roundUpToNextMinute(originalExpirationTimeInMilli);
    8.  
      if (toExpire != originalRoundedUp) {
    9.  
      String expireKey = getExpirationKey(originalRoundedUp);
    10.  
      this.redis.boundSetOps(expireKey).remove(keyToExpire);
    11.  
      }
    12.  
      }
    13.  
       
    14.  
      long sessionExpireInSeconds = session.getMaxInactiveIntervalInSeconds();
    15.  
      String sessionKey = getSessionKey(keyToExpire);
    16.  
       
    17.  
      if (sessionExpireInSeconds < 0) {
    18.  
      this.redis.boundValueOps(sessionKey).append("");
    19.  
      this.redis.boundValueOps(sessionKey).persist();
    20.  
      this.redis.boundHashOps(getSessionKey(session.getId())).persist();
    21.  
      return;
    22.  
      }
    23.  
       
    24.  
      String expireKey = getExpirationKey(toExpire);
    25.  
      BoundSetOperations<Object, Object> expireOperations = this.redis
    26.  
      .boundSetOps(expireKey);
    27.  
      expireOperations.add(keyToExpire);
    28.  
      /**
    29.  
      *关键在此处,在设置的基础上增加了5分钟
    30.  
      /
    31.  
      long fiveMinutesAfterExpires = sessionExpireInSeconds
    32.  
      + TimeUnit.MINUTES.toSeconds(5);
    33.  
       
    34.  
      expireOperations.expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
    35.  
      if (sessionExpireInSeconds == 0) {
    36.  
      this.redis.delete(sessionKey);
    37.  
      }
    38.  
      else {
    39.  
      this.redis.boundValueOps(sessionKey).append("");
    40.  
      this.redis.boundValueOps(sessionKey).expire(sessionExpireInSeconds,
    41.  
      TimeUnit.SECONDS);
    42.  
      }
    43.  
      this.redis.boundHashOps(getSessionKey(session.getId()))
    44.  
      .expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
    45.  
      }
    46.  
  • 相关阅读:
    Linux 分区与挂载
    Linux Shell 编程总结
    Java AtomicIntegerFieldUpdater 抽象类
    Java 内部类加载顺序
    Java AtomicIntegerArray 类
    Java AtomicInteger 类
    Java ReentrantLock 类
    Java Runnable 接口
    Java Supplier 接口
    Java Consumer 接口
  • 原文地址:https://www.cnblogs.com/bruce1992/p/13888047.html
Copyright © 2011-2022 走看看