欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-18 20:34:58
spring: session: timeout: 120首先看下@EnableRedisHttpSession注解属性@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Import(RedisHttpSessionConfiguration.class)@Configuration(proxyBeanMethods = false)public @interface EnableRed...
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功能也可以开启,如果有错,可以在评论区指出。

本文地址:https://blog.csdn.net/firstbaby/article/details/112008322