Add support for customizing session repository before initialization

This commit adds support for customizing session repository implementations (both SessionRepository and ReactiveSessionRepository) before initialization by introducing SessionRepositoryCustomizer and ReactiveSessionRepositoryCustomizer strategies.

Resolves: #1499
This commit is contained in:
Vedran Pavic
2019-08-30 23:29:57 +02:00
parent f746233255
commit df3e4c5bc1
10 changed files with 244 additions and 0 deletions

View File

@@ -18,8 +18,10 @@ package org.springframework.session.data.redis.config.annotation.web.http;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import org.apache.commons.logging.LogFactory;
@@ -51,6 +53,7 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
@@ -103,6 +106,8 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
private Executor redisSubscriptionExecutor;
private List<SessionRepositoryCustomizer<RedisOperationsSessionRepository>> sessionRepositoryCustomizers;
private ClassLoader classLoader;
private StringValueResolver embeddedValueResolver;
@@ -123,6 +128,8 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
sessionRepository.setSaveMode(this.saveMode);
int database = resolveDatabase();
sessionRepository.setDatabase(database);
this.sessionRepositoryCustomizers
.forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository));
return sessionRepository;
}
@@ -221,6 +228,12 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
this.redisSubscriptionExecutor = redisSubscriptionExecutor;
}
@Autowired(required = false)
public void setSessionRepositoryCustomizer(
ObjectProvider<SessionRepositoryCustomizer<RedisOperationsSessionRepository>> sessionRepositoryCustomizers) {
this.sessionRepositoryCustomizers = sessionRepositoryCustomizers.orderedStream().collect(Collectors.toList());
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;

View File

@@ -16,7 +16,9 @@
package org.springframework.session.data.redis.config.annotation.web.server;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.ObjectProvider;
@@ -36,6 +38,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
import org.springframework.session.config.annotation.web.server.SpringWebSessionConfiguration;
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository;
import org.springframework.session.data.redis.RedisFlushMode;
@@ -68,6 +71,8 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
private RedisSerializer<Object> defaultRedisSerializer;
private List<ReactiveSessionRepositoryCustomizer<ReactiveRedisOperationsSessionRepository>> sessionRepositoryCustomizers;
private ClassLoader classLoader;
private StringValueResolver embeddedValueResolver;
@@ -82,6 +87,8 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
sessionRepository.setRedisKeyNamespace(this.redisNamespace);
}
sessionRepository.setSaveMode(this.saveMode);
this.sessionRepositoryCustomizers
.forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository));
return sessionRepository;
}
@@ -120,6 +127,12 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
this.defaultRedisSerializer = defaultRedisSerializer;
}
@Autowired(required = false)
public void setSessionRepositoryCustomizer(
ObjectProvider<ReactiveSessionRepositoryCustomizer<ReactiveRedisOperationsSessionRepository>> sessionRepositoryCustomizers) {
this.sessionRepositoryCustomizers = sessionRepositoryCustomizers.orderedStream().collect(Collectors.toList());
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;

View File

@@ -29,6 +29,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
@@ -36,6 +37,7 @@ import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.session.FlushMode;
import org.springframework.session.SaveMode;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory;
@@ -57,6 +59,8 @@ import static org.mockito.Mockito.mock;
@SuppressWarnings("deprecation")
class RedisHttpSessionConfigurationTests {
private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
private static final String CLEANUP_CRON_EXPRESSION = "0 0 * * * *";
private AnnotationConfigApplicationContext context;
@@ -238,6 +242,15 @@ class RedisHttpSessionConfigurationTests {
assertThat(beans).containsKeys("springSessionRedisMessageListenerContainer", "redisMessageListenerContainer");
}
@Test
void sessionRepositoryCustomizer() {
registerAndRefresh(RedisConfig.class, SessionRepositoryCustomizerConfiguration.class);
RedisOperationsSessionRepository sessionRepository = this.context
.getBean(RedisOperationsSessionRepository.class);
assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh();
@@ -416,4 +429,22 @@ class RedisHttpSessionConfigurationTests {
}
@EnableRedisHttpSession
static class SessionRepositoryCustomizerConfiguration {
@Bean
@Order(0)
public SessionRepositoryCustomizer<RedisOperationsSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
}
@Bean
@Order(1)
public SessionRepositoryCustomizer<RedisOperationsSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository
.setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
}
}

View File

@@ -25,11 +25,13 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.SaveMode;
import org.springframework.session.config.ReactiveSessionRepositoryCustomizer;
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.SpringSessionRedisOperations;
@@ -222,6 +224,15 @@ class RedisWebSessionConfigurationTests {
"serializer")).isEqualTo(redisSerializer);
}
@Test
void sessionRepositoryCustomizer() {
registerAndRefresh(RedisConfig.class, SessionRepositoryCustomizerConfiguration.class);
ReactiveRedisOperationsSessionRepository sessionRepository = this.context
.getBean(ReactiveRedisOperationsSessionRepository.class);
assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh();
@@ -348,4 +359,22 @@ class RedisWebSessionConfigurationTests {
}
@EnableRedisWebSession
static class SessionRepositoryCustomizerConfiguration {
@Bean
@Order(0)
public ReactiveSessionRepositoryCustomizer<ReactiveRedisOperationsSessionRepository> sessionRepositoryCustomizerOne() {
return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
}
@Bean
@Order(1)
public ReactiveSessionRepositoryCustomizer<ReactiveRedisOperationsSessionRepository> sessionRepositoryCustomizerTwo() {
return (sessionRepository) -> sessionRepository
.setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS);
}
}
}