Browse Source
This implementation was inspired in large part by the cache auto-configuration. In addition to the originally supported Redis, now Hazelcast, an in-memory map, as well as a no-op option are supported. It should be easy to extend this to include additional data stores in the future. Closes gh-3811pull/5836/merge
9 changed files with 457 additions and 36 deletions
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
|
||||
import com.hazelcast.core.HazelcastInstance; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.autoconfigure.web.ServerProperties; |
||||
import org.springframework.context.annotation.Conditional; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.session.MapSessionRepository; |
||||
import org.springframework.session.SessionRepository; |
||||
import org.springframework.session.hazelcast.config.annotation.web.http.EnableHazelcastHttpSession; |
||||
import org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration; |
||||
|
||||
/** |
||||
* Hazelcast backed session auto-configuration. |
||||
* |
||||
* @author Tommy Ludwig |
||||
* @since 1.4.0 |
||||
*/ |
||||
@Configuration |
||||
@ConditionalOnClass({ HazelcastInstance.class, HazelcastHttpSessionConfiguration.class }) |
||||
@ConditionalOnMissingBean({ SessionRepository.class, HazelcastHttpSessionConfiguration.class }) |
||||
@EnableHazelcastHttpSession |
||||
@Conditional(SessionCondition.class) |
||||
class HazelcastSessionConfiguration { |
||||
|
||||
private final ServerProperties serverProperties; |
||||
|
||||
private final MapSessionRepository sessionRepository; |
||||
|
||||
HazelcastSessionConfiguration(ServerProperties serverProperties, MapSessionRepository sessionRepository) { |
||||
this.serverProperties = serverProperties; |
||||
this.sessionRepository = sessionRepository; |
||||
} |
||||
|
||||
@PostConstruct |
||||
public void applyConfigurationProperties() { |
||||
Integer timeout = this.serverProperties.getSession().getTimeout(); |
||||
if (timeout != null) { |
||||
this.sessionRepository.setDefaultMaxInactiveInterval(timeout); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.context.annotation.Conditional; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.session.SessionRepository; |
||||
|
||||
/** |
||||
* No-op session configuration used to disable Spring Session auto configuration via the |
||||
* environment. |
||||
* |
||||
* @author Tommy Ludwig |
||||
* @since 1.4.0 |
||||
*/ |
||||
@Configuration |
||||
@ConditionalOnMissingBean(SessionRepository.class) |
||||
@Conditional(SessionCondition.class) |
||||
class NoOpSessionConfiguration { |
||||
} |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.autoconfigure.web.ServerProperties; |
||||
import org.springframework.context.annotation.Conditional; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
||||
import org.springframework.session.SessionRepository; |
||||
import org.springframework.session.data.redis.RedisOperationsSessionRepository; |
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; |
||||
import org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration; |
||||
|
||||
/** |
||||
* Redis backed session auto-configuration. |
||||
* |
||||
* @author Andy Wilkinson |
||||
* @author Tommy Ludwig |
||||
* @since 1.4.0 |
||||
*/ |
||||
@Configuration |
||||
@ConditionalOnClass(RedisConnectionFactory.class) |
||||
@ConditionalOnMissingBean({ SessionRepository.class, RedisHttpSessionConfiguration.class }) |
||||
@EnableRedisHttpSession |
||||
@Conditional(SessionCondition.class) |
||||
class RedisSessionConfiguration { |
||||
|
||||
private final ServerProperties serverProperties; |
||||
|
||||
private final RedisOperationsSessionRepository sessionRepository; |
||||
|
||||
RedisSessionConfiguration(ServerProperties serverProperties, RedisOperationsSessionRepository sessionRepository) { |
||||
this.serverProperties = serverProperties; |
||||
this.sessionRepository = sessionRepository; |
||||
} |
||||
|
||||
@PostConstruct |
||||
public void applyConfigurationProperties() { |
||||
Integer timeout = this.serverProperties.getSession().getTimeout(); |
||||
if (timeout != null) { |
||||
this.sessionRepository.setDefaultMaxInactiveInterval(timeout); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome; |
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition; |
||||
import org.springframework.boot.bind.RelaxedPropertyResolver; |
||||
import org.springframework.context.annotation.ConditionContext; |
||||
import org.springframework.core.type.AnnotatedTypeMetadata; |
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
|
||||
/** |
||||
* General condition used by all session auto-configuration classes. |
||||
* |
||||
* @author Tommy Ludwig |
||||
*/ |
||||
class SessionCondition extends SpringBootCondition { |
||||
|
||||
@Override |
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, |
||||
AnnotatedTypeMetadata metadata) { |
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver( |
||||
context.getEnvironment(), "spring.session.store."); |
||||
if (!resolver.containsProperty("type")) { |
||||
return ConditionOutcome.match("Automatic session store type"); |
||||
} |
||||
SessionStoreType sessionStoreType = SessionStoreMappings |
||||
.getType(((AnnotationMetadata) metadata).getClassName()); |
||||
String value = resolver.getProperty("type").replace("-", "_").toUpperCase(); |
||||
if (value.equals(sessionStoreType.name())) { |
||||
return ConditionOutcome.match("Session store type " + sessionStoreType); |
||||
} |
||||
return ConditionOutcome.noMatch("Session store type " + value); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties; |
||||
|
||||
/** |
||||
* Properties for configuring Spring Session's auto-configuration. |
||||
* |
||||
* @author Tommy Ludwig |
||||
* @since 1.4.0 |
||||
*/ |
||||
@ConfigurationProperties("spring.session") |
||||
public class SessionProperties { |
||||
|
||||
private Store store; |
||||
|
||||
public Store getStore() { |
||||
return this.store; |
||||
} |
||||
|
||||
public void setStore(Store store) { |
||||
this.store = store; |
||||
} |
||||
|
||||
/** |
||||
* Session store-specific properties. |
||||
*/ |
||||
public static class Store { |
||||
/** |
||||
* Session data store type, auto-detected according to the environment by default. |
||||
*/ |
||||
private SessionStoreType type; |
||||
|
||||
public SessionStoreType getType() { |
||||
return this.type; |
||||
} |
||||
|
||||
public void setType(SessionStoreType type) { |
||||
this.type = type; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Mappings between {@link SessionStoreType} and {@code @Configuration}. |
||||
* |
||||
* @author Tommy Ludwig |
||||
*/ |
||||
final class SessionStoreMappings { |
||||
|
||||
private SessionStoreMappings() { |
||||
} |
||||
|
||||
private static final Map<SessionStoreType, Class<?>> MAPPINGS; |
||||
|
||||
static { |
||||
Map<SessionStoreType, Class<?>> mappings = new HashMap<SessionStoreType, Class<?>>(); |
||||
mappings.put(SessionStoreType.REDIS, RedisSessionConfiguration.class); |
||||
mappings.put(SessionStoreType.HAZELCAST, HazelcastSessionConfiguration.class); |
||||
mappings.put(SessionStoreType.SIMPLE, SimpleSessionConfiguration.class); |
||||
mappings.put(SessionStoreType.NONE, NoOpSessionConfiguration.class); |
||||
MAPPINGS = Collections.unmodifiableMap(mappings); |
||||
} |
||||
|
||||
public static String getConfigurationClass(SessionStoreType sessionStoreType) { |
||||
Class<?> configurationClass = MAPPINGS.get(sessionStoreType); |
||||
Assert.state(configurationClass != null, |
||||
"Unknown session store type " + sessionStoreType); |
||||
return configurationClass.getName(); |
||||
} |
||||
|
||||
public static SessionStoreType getType(String configurationClassName) { |
||||
for (Map.Entry<SessionStoreType, Class<?>> entry : MAPPINGS.entrySet()) { |
||||
if (entry.getValue().getName().equals(configurationClassName)) { |
||||
return entry.getKey(); |
||||
} |
||||
} |
||||
throw new IllegalStateException( |
||||
"Unknown configuration class " + configurationClassName); |
||||
} |
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
/** |
||||
* Supported Spring Session data store types. |
||||
* |
||||
* @author Tommy Ludwig |
||||
* @since 1.4.0 |
||||
*/ |
||||
public enum SessionStoreType { |
||||
|
||||
/** |
||||
* Redis backed sessions. |
||||
*/ |
||||
REDIS, |
||||
|
||||
/** |
||||
* Hazelcast backed sessions. |
||||
*/ |
||||
HAZELCAST, |
||||
|
||||
/** |
||||
* Simple in-memory map of sessions. |
||||
*/ |
||||
SIMPLE, |
||||
|
||||
/** |
||||
* No session datastore. |
||||
*/ |
||||
NONE; |
||||
|
||||
} |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.autoconfigure.session; |
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.autoconfigure.web.ServerProperties; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Conditional; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.session.ExpiringSession; |
||||
import org.springframework.session.MapSessionRepository; |
||||
import org.springframework.session.SessionRepository; |
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession; |
||||
|
||||
/** |
||||
* In-memory session configuration, intended as a fallback. |
||||
* |
||||
* @author Tommy Ludwig |
||||
* @since 1.4.0 |
||||
*/ |
||||
@Configuration |
||||
@ConditionalOnMissingBean(SessionRepository.class) |
||||
@EnableSpringHttpSession |
||||
@Conditional(SessionCondition.class) |
||||
class SimpleSessionConfiguration { |
||||
|
||||
@Bean |
||||
public SessionRepository<ExpiringSession> sessionRepository(ServerProperties serverProperties) { |
||||
MapSessionRepository sessionRepository = new MapSessionRepository(); |
||||
|
||||
Integer timeout = serverProperties.getSession().getTimeout(); |
||||
if (serverProperties.getSession().getTimeout() != null) { |
||||
sessionRepository.setDefaultMaxInactiveInterval(timeout); |
||||
} |
||||
return sessionRepository; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue