关于使用了@EnableRedisHttpSession注解,在配置文件中加入timeout 无效的原因

spring:
  session:
    timeout: 120

首先看下@EnableRedisHttpSession注解属性

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RedisHttpSessionConfiguration.class)
@Configuration(proxyBeanMethods = false)
public @interface EnableRedisHttpSession {

   /**
    * The session timeout in seconds. By default, it is set to 1800 seconds (30 minutes).
    * This should be a non-negative integer.
    * @return the seconds a session can be inactive before expiring
    */
   int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
  
   String redisNamespace() default RedisIndexedSessionRepository.DEFAULT_NAMESPACE;
   @Deprecated
   RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;

   FlushMode flushMode() default FlushMode.ON_SAVE;

   String cleanupCron() default RedisHttpSessionConfiguration.DEFAULT_CLEANUP_CRON;

   SaveMode saveMode() default SaveMode.ON_SET_ATTRIBUTE;

}

可见默认时间 maxInactiveIntervalInSeconds 为30 min

这里先说结果:
如果配置了@EnableRedisHttpSession 注解,在配置文件中设置超时时间是无效的。
只能在@EnableRedisHttpSession声明超时时间是有效的

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 120)//设置超时时间是120秒

原因:
配置文件中的spring.session.timout的作用值,会在RedisSessionConfiguration 起作用

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ RedisTemplate.class, RedisIndexedSessionRepository.class })
@ConditionalOnMissingBean(SessionRepository.class)
@ConditionalOnBean(RedisConnectionFactory.class)
@Conditional(ServletSessionCondition.class)
@EnableConfigurationProperties(RedisSessionProperties.class)
class RedisSessionConfiguration {

   	@Autowired
   	public void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
   			ServerProperties serverProperties) {  
   			// 获取配置文件的超时时间
   		Duration timeout = sessionProperties
   				.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout());
   		if (timeout != null) {
   			setMaxInactiveIntervalInSeconds((int) timeout.getSeconds());
   		}
   		setRedisNamespace(redisSessionProperties.getNamespace());
   		setFlushMode(redisSessionProperties.getFlushMode());
   		setSaveMode(redisSessionProperties.getSaveMode());
   		setCleanupCron(redisSessionProperties.getCleanupCron());
   	}
   }
}

如果标注了@EnableRedisHttpSession 注解,这个类就不会被加载,不会起作用了。
原因:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RedisHttpSessionConfiguration.class)  // @EnableRedisHttpSession  给容器中导入 RedisHttpSessionConfiguration 组件
@Configuration(proxyBeanMethods = false) 
public @interface EnableRedisHttpSession {

RedisHttpSessionConfiguration有两个核心的地方

// 1 给容器中加入 RedisIndexedSessionRepository  这个是真正对redis操作的组件,超时时间也在这个组件中真正的起作用
@Bean
   public RedisIndexedSessionRepository sessionRepository() {
   	RedisTemplate<Object, Object> redisTemplate = createRedisTemplate();
   	RedisIndexedSessionRepository sessionRepository = new RedisIndexedSessionRepository(redisTemplate);
   	sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);
   	if (this.indexResolver != null) {
   		sessionRepository.setIndexResolver(this.indexResolver);
   	}
   	if (this.defaultRedisSerializer != null) {
   		sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
   	}
   	// 真正超时时间起作用的地方
   	sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
   	if (StringUtils.hasText(this.redisNamespace)) {
   		sessionRepository.setRedisKeyNamespace(this.redisNamespace);
   	}
   	sessionRepository.setFlushMode(this.flushMode);
   	sessionRepository.setSaveMode(this.saveMode);
   	int database = resolveDatabase();
   	sessionRepository.setDatabase(database);
   	this.sessionRepositoryCustomizers
   			.forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository));
   	return sessionRepository;
   }
// 2  解析 @EnableRedisHttpSession 注解,并且获取注解的属性
@Override
   @SuppressWarnings("deprecation")
   public void setImportMetadata(AnnotationMetadata importMetadata) {
   	Map<String, Object> attributeMap = importMetadata
   			.getAnnotationAttributes(EnableRedisHttpSession.class.getName());
   	AnnotationAttributes attributes = AnnotationAttributes.fromMap(attributeMap);
   	// 获取注解中的超时时间
   	this.maxInactiveIntervalInSeconds = attributes.getNumber("maxInactiveIntervalInSeconds");
   	String redisNamespaceValue = attributes.getString("redisNamespace");
   	if (StringUtils.hasText(redisNamespaceValue)) {
   		this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue);
   	}
   	FlushMode flushMode = attributes.getEnum("flushMode");
   	RedisFlushMode redisFlushMode = attributes.getEnum("redisFlushMode");
   	if (flushMode == FlushMode.ON_SAVE && redisFlushMode != RedisFlushMode.ON_SAVE) {
   		flushMode = redisFlushMode.getFlushMode();
   	}
   	this.flushMode = flushMode;
   	this.saveMode = attributes.getEnum("saveMode");
   	String cleanupCron = attributes.getString("cleanupCron");
   	if (StringUtils.hasText(cleanupCron)) {
   		this.cleanupCron = cleanupCron;
   	}
   }

当标注了这个注解后,RedisHttpSessionConfiguration就会生效,首先会解读@EnableRedisHttpSession 注解的属性,然后在容器中加入RedisIndexedSessionRepository 组件,会把注解中的超时时间值拿来,但是,此时的RedisSessionConfiguration配置就不会起作用,因为

@Configuration
@ConditionalOnClass({ RedisTemplate.class, RedisOperationsSessionRepository.class })
@ConditionalOnMissingBean(SessionRepository.class)  // 容器中没有SessionRepository 组件采用起作用,但是我们已经给容器中加入了RedisIndexedSessionRepository
@ConditionalOnBean(RedisConnectionFactory.class)
@Conditional(ServletSessionCondition.class)
@EnableConfigurationProperties(RedisSessionProperties.class)
class RedisSessionConfiguration {

所以下面的自动装配方法也不会起作用了,配置文件的属性spring.session.timout也就不会起作用了。

当然,如果关闭 @EnableRedisHttpSession 注解,配置文件的属性spring.session.timout就会起作用,此时的调用顺序: 先加载RedisSessionConfiguration 组件,然后调用自动装配的customize方法

public void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties)

然后 加载 RedisHttpSessionConfiguration 类中的RedisIndexedSessionRepository 组件,此时解析注解@EnableRedisHttpSessionsetImportMetadata方法,不会在起作用。
这也就解释了为什么加入 @EnableRedisHttpSession 配置文件属性不起作用的原因。
个人认为,不加@EnableRedisHttpSession 注解,SpringSession功能也可以开启,如果有错,可以在评论区指出。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值