Spring boot集成Redis实现sessions共享时,sessions过期时间问题分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
     Springboot鼓励零配置的方式,帮你做好大部分重复劳动的事,好到不能再好;具体的Redis安装方法和Springboot集成Redis方法,可以去搜索相关文章或参考该文章http://www.cnblogs.com/mengmeng89012/p/5519698.html。

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

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

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

    @Configuration
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds= 3600,redisNamespace = "tl")
    public class RedisSessionConfig {

    }

即开启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函数:
    public void setImportMetadata(AnnotationMetadata importMetadata) {

            Map<String, Object> enableAttrMap = importMetadata
                    .getAnnotationAttributes(EnableRedisHttpSession.class.getName());
            AnnotationAttributes enableAttrs = AnnotationAttributes.fromMap(enableAttrMap);
            /**
            *解析注解,获取maxInactiveIntervalInSeconds赋值给配置类的maxInactiveIntervalInSeconds对象
            */
            this.maxInactiveIntervalInSeconds = enableAttrs
                    .getNumber("maxInactiveIntervalInSeconds");
            String redisNamespaceValue = enableAttrs.getString("redisNamespace");
            /**
            *设置命名空间
            */
            if (StringUtils.hasText(redisNamespaceValue)) {
                this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue);
            }
            this.redisFlushMode = enableAttrs.getEnum("redisFlushMode");
        }
     利用Redis作为sessions共享仓实现类为org.springframework.session.data.redis.RedisOperationsSessionRepository
    其执行session过期策略的实现类为RedisSessionExpirationPolicy,其过期的具体函数如下:
    public void onExpirationUpdated(Long originalExpirationTimeInMilli,
                ExpiringSession session) {
            String keyToExpire = "expires:" + session.getId();
            long toExpire = roundUpToNextMinute(expiresInMillis(session));

            if (originalExpirationTimeInMilli != null) {
                long originalRoundedUp = roundUpToNextMinute(originalExpirationTimeInMilli);
                if (toExpire != originalRoundedUp) {
                    String expireKey = getExpirationKey(originalRoundedUp);
                    this.redis.boundSetOps(expireKey).remove(keyToExpire);
                }
            }

            long sessionExpireInSeconds = session.getMaxInactiveIntervalInSeconds();
            String sessionKey = getSessionKey(keyToExpire);

            if (sessionExpireInSeconds < 0) {
                this.redis.boundValueOps(sessionKey).append("");
                this.redis.boundValueOps(sessionKey).persist();
                this.redis.boundHashOps(getSessionKey(session.getId())).persist();
                return;
            }

            String expireKey = getExpirationKey(toExpire);
            BoundSetOperations<Object, Object> expireOperations = this.redis
                    .boundSetOps(expireKey);
            expireOperations.add(keyToExpire);
            /**
            *关键在此处,在设置的基础上增加了5分钟
            /
            long fiveMinutesAfterExpires = sessionExpireInSeconds
                    + TimeUnit.MINUTES.toSeconds(5);

            expireOperations.expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
            if (sessionExpireInSeconds == 0) {
                this.redis.delete(sessionKey);
            }
            else {
                this.redis.boundValueOps(sessionKey).append("");
                this.redis.boundValueOps(sessionKey).expire(sessionExpireInSeconds,
                        TimeUnit.SECONDS);
            }
            this.redis.boundHashOps(getSessionKey(session.getId()))
                    .expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
        }

来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring boot集成Redis实现sessions共享时,sessions过期时间问题分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏