Add session property for ConfigureRedisAction
Add a new property to `RedisSessionProperties` that allows the default `ConfigureRedisAction` to be changed. Users can still also configure the action using a `@Bean`. See gh-17022
This commit is contained in:
parent
2888ddee22
commit
a0fabc9851
|
@ -22,13 +22,17 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.session.RedisSessionProperties.ConfigurationStrategy;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.session.SessionRepository;
|
import org.springframework.session.SessionRepository;
|
||||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
|
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
|
||||||
|
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
|
||||||
|
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
|
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,6 +66,19 @@ class RedisSessionConfiguration {
|
||||||
setCleanupCron(redisSessionProperties.getCleanupCron());
|
setCleanupCron(redisSessionProperties.getCleanupCron());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ConfigureRedisAction configureRedisAction(RedisSessionProperties redisSessionProperties) {
|
||||||
|
ConfigurationStrategy strategy = redisSessionProperties.getConfigurationStrategy();
|
||||||
|
if (strategy == ConfigurationStrategy.NOTIFY_KEYSPACE_EVENTS) {
|
||||||
|
return new ConfigureNotifyKeyspaceEventsAction();
|
||||||
|
}
|
||||||
|
if (strategy == ConfigurationStrategy.NO_OP) {
|
||||||
|
return ConfigureRedisAction.NO_OP;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Strategy '" + strategy + "' is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2017 the original author or authors.
|
* Copyright 2012-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -40,6 +40,11 @@ public class RedisSessionProperties {
|
||||||
*/
|
*/
|
||||||
private RedisFlushMode flushMode = RedisFlushMode.ON_SAVE;
|
private RedisFlushMode flushMode = RedisFlushMode.ON_SAVE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows specifying a strategy for configuring and validating Redis.
|
||||||
|
*/
|
||||||
|
private ConfigurationStrategy configurationStrategy = ConfigurationStrategy.NOTIFY_KEYSPACE_EVENTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cron expression for expired session cleanup job.
|
* Cron expression for expired session cleanup job.
|
||||||
*/
|
*/
|
||||||
|
@ -69,4 +74,29 @@ public class RedisSessionProperties {
|
||||||
this.cleanupCron = cleanupCron;
|
this.cleanupCron = cleanupCron;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConfigurationStrategy getConfigurationStrategy() {
|
||||||
|
return this.configurationStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigurationStrategy(ConfigurationStrategy configurationStrategy) {
|
||||||
|
this.configurationStrategy = configurationStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows specifying a strategy for configuring and validating Redis.
|
||||||
|
*/
|
||||||
|
public enum ConfigurationStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do nothing.
|
||||||
|
*/
|
||||||
|
NO_OP,
|
||||||
|
/**
|
||||||
|
* Ensures that Redis Keyspace events for Generic commands and Expired events are
|
||||||
|
* enabled.
|
||||||
|
*/
|
||||||
|
NOTIFY_KEYSPACE_EVENTS
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.session;
|
package org.springframework.boot.autoconfigure.session;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
|
|
||||||
|
@ -28,13 +30,18 @@ import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||||
import org.springframework.boot.testsupport.testcontainers.DisabledWithoutDockerTestcontainers;
|
import org.springframework.boot.testsupport.testcontainers.DisabledWithoutDockerTestcontainers;
|
||||||
import org.springframework.boot.testsupport.testcontainers.RedisContainer;
|
import org.springframework.boot.testsupport.testcontainers.RedisContainer;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnection;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
|
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
|
||||||
import org.springframework.session.data.redis.RedisFlushMode;
|
import org.springframework.session.data.redis.RedisFlushMode;
|
||||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
|
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
|
||||||
|
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
|
||||||
|
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||||
import org.springframework.session.hazelcast.HazelcastSessionRepository;
|
import org.springframework.session.hazelcast.HazelcastSessionRepository;
|
||||||
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
|
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis specific tests for {@link SessionAutoConfiguration}.
|
* Redis specific tests for {@link SessionAutoConfiguration}.
|
||||||
|
@ -81,6 +88,34 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||||
.run(validateSpringSessionUsesRedis("foo:event:0:created:", RedisFlushMode.IMMEDIATE, "0 0 12 * * *"));
|
.run(validateSpringSessionUsesRedis("foo:event:0:created:", RedisFlushMode.IMMEDIATE, "0 0 12 * * *"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void redisSessionConfigureNoStrategy() {
|
||||||
|
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||||
|
.withPropertyValues("spring.session.store-type=redis",
|
||||||
|
"spring.session.redis.configuration-strategy=no_op",
|
||||||
|
"spring.redis.port=" + redis.getFirstMappedPort())
|
||||||
|
.run(validateStrategy(ConfigureRedisAction.NO_OP.getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void redisSessionConfigureDefaultStrategy() {
|
||||||
|
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||||
|
.withPropertyValues("spring.session.store-type=redis",
|
||||||
|
"spring.redis.port=" + redis.getFirstMappedPort())
|
||||||
|
.run(validateStrategy(ConfigureNotifyKeyspaceEventsAction.class,
|
||||||
|
entry("notify-keyspace-events", "gxE")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void redisSessionConfigureCustomStrategy() {
|
||||||
|
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||||
|
.withUserConfiguration(MaxEntriesRedisAction.class)
|
||||||
|
.withPropertyValues("spring.session.store-type=redis",
|
||||||
|
"spring.redis.port=" + redis.getFirstMappedPort())
|
||||||
|
.run(validateStrategy(MaxEntriesRedisAction.class, entry("set-max-intset-entries", "1024")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesRedis(
|
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesRedis(
|
||||||
String sessionCreatedChannelPrefix, RedisFlushMode flushMode, String cleanupCron) {
|
String sessionCreatedChannelPrefix, RedisFlushMode flushMode, String cleanupCron) {
|
||||||
return (context) -> {
|
return (context) -> {
|
||||||
|
@ -94,4 +129,25 @@ class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfiguratio
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ContextConsumer<AssertableWebApplicationContext> validateStrategy(
|
||||||
|
Class<? extends ConfigureRedisAction> actionClass, Map.Entry... values) {
|
||||||
|
return (context) -> {
|
||||||
|
assertThat(context).hasSingleBean(ConfigureRedisAction.class).hasSingleBean(RedisConnectionFactory.class);
|
||||||
|
assertThat(context.getBean(ConfigureRedisAction.class)).isInstanceOf(actionClass);
|
||||||
|
RedisConnection connection = context.getBean(RedisConnectionFactory.class).getConnection();
|
||||||
|
if (values.length > 0) {
|
||||||
|
assertThat(connection.getConfig("*")).contains(values);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MaxEntriesRedisAction implements ConfigureRedisAction {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(RedisConnection connection) {
|
||||||
|
connection.setConfig("set-max-intset-entries", "1024");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue