3232import org .springframework .context .annotation .Bean ;
3333import org .springframework .context .annotation .Configuration ;
3434import org .springframework .context .annotation .ImportAware ;
35- import org .springframework .context .support .PropertySourcesPlaceholderConfigurer ;
3635import org .springframework .core .annotation .AnnotationAttributes ;
3736import org .springframework .core .type .AnnotationMetadata ;
3837import org .springframework .data .redis .connection .RedisConnection ;
4342import org .springframework .data .redis .serializer .RedisSerializer ;
4443import org .springframework .data .redis .serializer .StringRedisSerializer ;
4544import org .springframework .scheduling .annotation .EnableScheduling ;
45+ import org .springframework .scheduling .annotation .SchedulingConfigurer ;
46+ import org .springframework .scheduling .config .ScheduledTaskRegistrar ;
4647import org .springframework .session .config .annotation .web .http .SpringHttpSessionConfiguration ;
4748import org .springframework .session .data .redis .RedisFlushMode ;
4849import org .springframework .session .data .redis .RedisOperationsSessionRepository ;
6869@ Configuration
6970@ EnableScheduling
7071public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
71- implements EmbeddedValueResolverAware , ImportAware {
72+ implements EmbeddedValueResolverAware , ImportAware , SchedulingConfigurer {
73+
74+ static final String DEFAULT_CLEANUP_CRON = "0 * * * * *" ;
7275
7376 private Integer maxInactiveIntervalInSeconds = 1800 ;
7477
7578 private String redisNamespace = "" ;
7679
7780 private RedisFlushMode redisFlushMode = RedisFlushMode .ON_SAVE ;
7881
82+ private String cleanupCron = DEFAULT_CLEANUP_CRON ;
83+
7984 private ConfigureRedisAction configureRedisAction = new ConfigureNotifyKeyspaceEventsAction ();
8085
8186 private RedisConnectionFactory redisConnectionFactory ;
8287
8388 private RedisSerializer <Object > defaultRedisSerializer ;
8489
90+ private ApplicationEventPublisher applicationEventPublisher ;
91+
8592 private Executor redisTaskExecutor ;
8693
8794 private Executor redisSubscriptionExecutor ;
8895
8996 private StringValueResolver embeddedValueResolver ;
9097
9198 @ Bean
92- public RedisOperationsSessionRepository sessionRepository (
93- ApplicationEventPublisher applicationEventPublisher ) {
99+ public RedisOperationsSessionRepository sessionRepository () {
94100 RedisTemplate <Object , Object > redisTemplate = createRedisTemplate (
95101 this .redisConnectionFactory , this .defaultRedisSerializer );
96102 RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository (
97103 redisTemplate );
98- sessionRepository .setApplicationEventPublisher (applicationEventPublisher );
104+ sessionRepository .setApplicationEventPublisher (this . applicationEventPublisher );
99105 if (this .defaultRedisSerializer != null ) {
100106 sessionRepository .setDefaultSerializer (this .defaultRedisSerializer );
101107 }
102108 sessionRepository
103109 .setDefaultMaxInactiveInterval (this .maxInactiveIntervalInSeconds );
104- String redisNamespace = getRedisNamespace ();
105- if (StringUtils .hasText (redisNamespace )) {
106- sessionRepository .setRedisKeyNamespace (redisNamespace );
110+ if (StringUtils .hasText (this .redisNamespace )) {
111+ sessionRepository .setRedisKeyNamespace (this .redisNamespace );
107112 }
108113 sessionRepository .setRedisFlushMode (this .redisFlushMode );
109114 return sessionRepository ;
@@ -135,15 +140,6 @@ public InitializingBean enableRedisKeyspaceNotificationsInitializer() {
135140 this .redisConnectionFactory , this .configureRedisAction );
136141 }
137142
138- /**
139- * Property placeholder to process the @Scheduled annotation.
140- * @return the {@link PropertySourcesPlaceholderConfigurer} to use
141- */
142- @ Bean
143- public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer () {
144- return new PropertySourcesPlaceholderConfigurer ();
145- }
146-
147143 public void setMaxInactiveIntervalInSeconds (int maxInactiveIntervalInSeconds ) {
148144 this .maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds ;
149145 }
@@ -157,6 +153,10 @@ public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
157153 this .redisFlushMode = redisFlushMode ;
158154 }
159155
156+ public void setCleanupCron (String cleanupCron ) {
157+ this .cleanupCron = cleanupCron ;
158+ }
159+
160160 /**
161161 * Sets the action to perform for configuring Redis.
162162 *
@@ -187,6 +187,12 @@ public void setDefaultRedisSerializer(
187187 this .defaultRedisSerializer = defaultRedisSerializer ;
188188 }
189189
190+ @ Autowired
191+ public void setApplicationEventPublisher (
192+ ApplicationEventPublisher applicationEventPublisher ) {
193+ this .applicationEventPublisher = applicationEventPublisher ;
194+ }
195+
190196 @ Autowired (required = false )
191197 @ Qualifier ("springSessionRedisTaskExecutor" )
192198 public void setRedisTaskExecutor (Executor redisTaskExecutor ) {
@@ -206,17 +212,27 @@ public void setEmbeddedValueResolver(StringValueResolver resolver) {
206212
207213 @ Override
208214 public void setImportMetadata (AnnotationMetadata importMetadata ) {
209- Map <String , Object > enableAttrMap = importMetadata
215+ Map <String , Object > attributeMap = importMetadata
210216 .getAnnotationAttributes (EnableRedisHttpSession .class .getName ());
211- AnnotationAttributes enableAttrs = AnnotationAttributes .fromMap (enableAttrMap );
212- this .maxInactiveIntervalInSeconds = enableAttrs
217+ AnnotationAttributes attributes = AnnotationAttributes .fromMap (attributeMap );
218+ this .maxInactiveIntervalInSeconds = attributes
213219 .getNumber ("maxInactiveIntervalInSeconds" );
214- String redisNamespaceValue = enableAttrs .getString ("redisNamespace" );
220+ String redisNamespaceValue = attributes .getString ("redisNamespace" );
215221 if (StringUtils .hasText (redisNamespaceValue )) {
216222 this .redisNamespace = this .embeddedValueResolver
217223 .resolveStringValue (redisNamespaceValue );
218224 }
219- this .redisFlushMode = enableAttrs .getEnum ("redisFlushMode" );
225+ this .redisFlushMode = attributes .getEnum ("redisFlushMode" );
226+ String cleanupCron = attributes .getString ("cleanupCron" );
227+ if (StringUtils .hasText (cleanupCron )) {
228+ this .cleanupCron = cleanupCron ;
229+ }
230+ }
231+
232+ @ Override
233+ public void configureTasks (ScheduledTaskRegistrar taskRegistrar ) {
234+ taskRegistrar .addCronTask (() -> sessionRepository ().cleanupExpiredSessions (),
235+ this .cleanupCron );
220236 }
221237
222238 private static RedisTemplate <Object , Object > createRedisTemplate (
@@ -233,13 +249,6 @@ private static RedisTemplate<Object, Object> createRedisTemplate(
233249 return redisTemplate ;
234250 }
235251
236- private String getRedisNamespace () {
237- if (StringUtils .hasText (this .redisNamespace )) {
238- return this .redisNamespace ;
239- }
240- return System .getProperty ("spring.session.redis.namespace" , "" );
241- }
242-
243252 /**
244253 * Ensures that Redis is configured to send keyspace notifications. This is important
245254 * to ensure that expiration and deletion of sessions trigger SessionDestroyedEvents.
0 commit comments