关于使用了@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
组件,此时解析注解@EnableRedisHttpSession
的setImportMetadata
方法,不会在起作用。
这也就解释了为什么加入 @EnableRedisHttpSession
配置文件属性不起作用的原因。
个人认为,不加@EnableRedisHttpSession
注解,SpringSession功能也可以开启,如果有错,可以在评论区指出。
本文地址:https://blog.csdn.net/firstbaby/article/details/112008322