Skip to content

Instantly share code, notes, and snippets.

@bro0k
Forked from guozi/ExpirationListener.java
Created February 15, 2019 04:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bro0k/3d2b93b8b973fc89f63b03f6973be352 to your computer and use it in GitHub Desktop.
Save bro0k/3d2b93b8b973fc89f63b03f6973be352 to your computer and use it in GitHub Desktop.
Spring Boot 2 + Spring Session 2 + Shiro 1.4 + Redis(Lettuce) Config
#缓存服务器
# REDIS (RedisProperties)
# Redis服务器连接端口
spring.redis.port=6379
# Redis数据库索引(默认为0)
spring.redis.database=1
#session存储数据库
spring.redis.secondary-database=2
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=25
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=80
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=-1ms
# 超时时间(毫秒)
spring.redis.lettuce.shutdown-timeout=200ms
#session过期(秒)
spring.redis.cookie-name=SESSION_ID
spring.redis.session-expire=1800
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* Session过期监听
* @author Frank Zeng
*
*/
@Slf4j
@Component
public class ExpirationListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
String key = new String(message.getBody());
log.debug("expired key: {}", key);
}
}
import java.lang.reflect.Method;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import lombok.extern.slf4j.Slf4j;
/**
* Redis服务器对象缓存配置(对象缓存)
*
* @author Frank.Zeng
*
*/
@Configuration
@EnableCaching
@Slf4j
public class MyRedisConfig extends CachingConfigurerSupport {
/**
* 加载属性文件数据
*
* @return
*/
@Bean
public MyRedisProperties redisProperties() {
return new MyRedisProperties();
}
/**
* RedisTemplate
*
* @return
*/
@SuppressWarnings("rawtypes")
@Primary
@Bean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
RedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setValueSerializer(sessionRedisSerializer());
template.setHashKeySerializer(stringSerializer);
template.setHashValueSerializer(sessionRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* 设置redisTemplate的存储格式(在此与Session没有什么关系)
*
* @return
*/
@SuppressWarnings("rawtypes")
@Bean
public RedisSerializer sessionRedisSerializer() {
return new Jackson2JsonRedisSerializer<Object>(Object.class);
}
/**
* 主键生成器
*
* @return
*/
@Bean
public KeyGenerator commonKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
String key = sb.toString();
log.info("key:" + key);
return key;
}
};
}
@Bean
public CacheManager cacheManager(
@Qualifier("connectionFactory") RedisConnectionFactory redisConnectionFactory) {
RedisCacheManager redisCacheManager = RedisCacheManager.create(redisConnectionFactory);
return redisCacheManager;
}
@Primary
@Bean(name = "connectionFactory")
public RedisConnectionFactory connectionFactory() {
// 单机版配置
RedisStandaloneConfiguration redisStandaloneConfiguration =
new RedisStandaloneConfiguration(redisProperties().getHost(), redisProperties().getPort());
redisStandaloneConfiguration.setDatabase(redisProperties().getDatabase());
redisStandaloneConfiguration.setPassword(RedisPassword.of(redisProperties().getPassword()));
// 集群版配置
// RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
// String[] serverArray = clusterNodes.split(",");
// Set<RedisNode> nodes = new HashSet<RedisNode>();
// for (String ipPort : serverArray) {
// String[] ipAndPort = ipPort.split(":");
// nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));
// }
// redisClusterConfiguration.setPassword(RedisPassword.of(password));
// redisClusterConfiguration.setClusterNodes(nodes);
// redisClusterConfiguration.setMaxRedirects(maxRedirects);
// 客户端配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();// 连接池配置
poolConfig.setMaxIdle(redisProperties().getLettuce().getPool().getMaxIdle());
poolConfig.setMaxTotal(redisProperties().getLettuce().getPool().getMaxActive());
poolConfig.setMaxWaitMillis(redisProperties().getLettuce().getPool().getMaxWait().toMillis());
poolConfig.setMinIdle(redisProperties().getLettuce().getPool().getMinIdle());
LettuceClientConfiguration lettuceClientConfiguration =
LettucePoolingClientConfiguration.builder().poolConfig(poolConfig)
.commandTimeout(redisProperties().getLettuce().getShutdownTimeout()).build();
LettuceConnectionFactory redisConnectionFactory =
new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
log.info("2.1 初始化Redis缓存服务器(普通对象)... ...");
return redisConnectionFactory;
}
}
import java.time.Duration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Data
@Configuration
@NoArgsConstructor
@ConfigurationProperties(prefix = "spring.redis")
public class MyRedisProperties {
/**
* Database index used by the connection factory.
*/
private int database = 0;
private int secondaryDatabase = 1;
/**
* Redis url, which will overrule host, port and password if set.
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
/**
* Enable SSL.
*/
private boolean ssl;
/**
* Connection timeout.
*/
private Duration timeout;
private int sessionExpire;
private String cookieName="SESSION_ID";
private final Lettuce lettuce = new Lettuce();
public Lettuce getLettuce() {
return this.lettuce;
}
/**
* Lettuce client properties.
*/
public static class Lettuce {
/**
* Shutdown timeout.
*/
private Duration shutdownTimeout = Duration.ofMillis(100);
/**
* Lettuce pool configuration.
*/
private Pool pool;
public Duration getShutdownTimeout() {
return this.shutdownTimeout;
}
public void setShutdownTimeout(Duration shutdownTimeout) {
this.shutdownTimeout = shutdownTimeout;
}
public Pool getPool() {
return this.pool;
}
public void setPool(Pool pool) {
this.pool = pool;
}
}
/**
* Pool properties.
*/
@Getter
@Setter
public static class Pool {
/**
* Max number of "idle" connections in the pool. Use a negative value to indicate an unlimited
* number of idle connections.
*/
private int maxIdle = 8;
/**
* Target for the minimum number of idle connections to maintain in the pool. This setting only
* has an effect if it is positive.
*/
private int minIdle = 0;
/**
* Max number of connections that can be allocated by the pool at a given time. Use a negative
* value for no limit.
*/
private int maxActive = 8;
/**
* Maximum amount of time (in milliseconds) a connection allocation should block before throwing
* an exception when the pool is exhausted. Use a negative value to block indefinitely.
*/
private Duration maxWait = Duration.ofMillis(-1);
}
}
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
<!-- redis专用线程池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 简化实体代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
/**
* redis序列化对象
*/
public class RedisObjectSerializer implements RedisSerializer<Object> {
private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();
static final byte[] EMPTY_ARRAY = new byte[0];
@Override
public Object deserialize(byte[] bytes) {
if (isEmpty(bytes)) {
return null;
}
try {
return deserializer.convert(bytes);
} catch (Exception ex) {
throw new SerializationException("Cannot deserialize", ex);
}
}
@Override
public byte[] serialize(Object object) {
if (object == null) {
return EMPTY_ARRAY;
}
try {
return serializer.convert(object);
} catch (Exception ex) {
return EMPTY_ARRAY;
}
}
private boolean isEmpty(byte[] data) {
return (data == null || data.length == 0);
}
}
import java.util.Map;
import javax.servlet.Filter;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieHttpSessionIdResolver;
import org.springframework.session.web.http.DefaultCookieSerializer;
import org.springframework.session.web.http.HttpSessionIdResolver;
import com.google.common.collect.Maps;
import com.rivers.shopkeeper.config.redis.MyRedisProperties;
import com.rivers.shopkeeper.utils.LocalConstants;
import lombok.extern.slf4j.Slf4j;
@EnableRedisHttpSession
@Configuration
@Slf4j
public class ShiroConfig {
/**
* 加载属性文件数据
*
* @return
*/
@Bean(name = "shiroProperties")
public MyRedisProperties shiroProperties() {
return new MyRedisProperties();
}
@Bean
HttpSessionIdResolver httpSessionResolver() {
CookieHttpSessionIdResolver httpSessionResolver = new CookieHttpSessionIdResolver();
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName(shiroProperties().getCookieName());
httpSessionResolver.setCookieSerializer(serializer);
return httpSessionResolver;// 客户端Session策略
}
/**
* 与Session有关设置链接
*
* @return
*/
@Bean
public RedisOperationsSessionRepository sessionRepository(ApplicationEventPublisher applicationEventPublisher) {
RedisOperationsSessionRepository repository = new RedisOperationsSessionRepository(shiroRedisTemplate());
repository.setApplicationEventPublisher(applicationEventPublisher);
// 设置session的有效时长
repository.setDefaultMaxInactiveInterval(shiroProperties().getSessionExpire());
return repository;
}
@Bean
RedisMessageListenerContainer keyExpirationListenerContainer(RedisConnectionFactory connectionFactory,
ExpirationListener expirationListener) {
RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory);
listenerContainer.addMessageListener(expirationListener,
new PatternTopic("__keyevent@" + shiroProperties().getSecondaryDatabase() + "__:expired"));// __keyevent@0__:expired
// 通道0表示db0
// 根据自己的dbindex选择合适的数字
listenerContainer.setErrorHandler(e -> log.error("redis session已过期", e));
return listenerContainer;
}
/**
* FilterRegistrationBean
*
* @return
*/
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistration.setEnabled(true);
filterRegistration.addUrlPatterns("/*");
filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
return filterRegistration;
}
/**
* @see org.apache.shiro.spring.web.ShiroFilterFactoryBean
* @return
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter() {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager());
bean.setLoginUrl("/login");
bean.setSuccessUrl("/");
bean.setUnauthorizedUrl("/401");
Map<String, Filter> filters = Maps.newHashMap();
filters.put("authc", formAuthenticationFilter());
filters.put("user", sysUserFilter());
filters.put("anon", new AnonymousFilter());
bean.setFilters(filters);
Map<String, String> chains = Maps.newHashMap();
chains.put("/login", "authc");
chains.put("/logout", "logout");
chains.put("/static/**", "anon");
chains.put("/css/**", "anon");
chains.put("/js/**", "anon");
chains.put("/bootstrap/**", "anon");
chains.put("/images/**", "anon");
chains.put("/error/**", "anon");
chains.put("/401", "anon");
chains.put("/druid/**", "anon");
chains.put("/authenticated", "authc");
chains.put("/s/**", "user");
chains.put("/", "user");
bean.setFilterChainDefinitionMap(chains);
return bean;
}
@Bean
public FormAuthenticationFilter formAuthenticationFilter() {
return new FormAuthenticationFilter();
}
@Bean
public SysUserFilter sysUserFilter() {
return new SysUserFilter();
}
/**
* 权限管理器
*
* @return
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
// 数据库认证的实现
manager.setRealm(shiroDbRealm());
// session 管理器
manager.setSessionManager(sessionManager());
// 缓存管理器
manager.setCacheManager(shrioRedisCacheManager());
// TODO:暂时未用
// manager.setRememberMeManager(rememberMeManager());
return manager;
}
// /**
// * cookie对象;
// *
// * @return
// */
// @Bean
// public SimpleCookie rememberMeCookie() {
// // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
// SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
// // 如果httyOnly设置为true,则客户端不会暴露给客户端脚本代码,使用HttpOnly cookie有助于减少某些类型的跨站点脚本攻击;
// simpleCookie.setHttpOnly(true);
// // <!-- 记住我cookie生效时间30天 ,单位秒;-->
// simpleCookie.setMaxAge(2592000);
// return simpleCookie;
// }
//
// /**
// * cookie管理对象;
// *
// * @return
// */
// @Bean
// public CookieRememberMeManager rememberMeManager() {
// CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
// byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
// cookieRememberMeManager.setCipherKey(cipherKey);
// cookieRememberMeManager.setCookie(rememberMeCookie());
// return cookieRememberMeManager;
// }
/**
* DefaultWebSessionManager
*
* @return
*/
@Bean(name = "sessionManager")
public ServletContainerSessionManager sessionManager() {
ServletContainerSessionManager sessionManager = new ServletContainerSessionManager();
return sessionManager;
}
/**
* @see UserRealm--->AuthorizingRealm
* @return
*/
@Bean
@DependsOn(value = {"lifecycleBeanPostProcessor", "shrioRedisCacheManager"})
public ShiroDbRealm shiroDbRealm() {
ShiroDbRealm userRealm = new ShiroDbRealm();
userRealm.setCacheManager(shrioRedisCacheManager());
userRealm.setCachingEnabled(true);
userRealm.setAuthenticationCachingEnabled(false);
userRealm.setAuthorizationCachingEnabled(true);
return userRealm;
}
@Bean(name = "shrioRedisCacheManager")
@DependsOn(value = "shiroRedisTemplate")
public ShrioRedisCacheManager shrioRedisCacheManager() {
ShrioRedisCacheManager cacheManager = new ShrioRedisCacheManager(shiroRedisTemplate());
cacheManager.createCache(LocalConstants.SHIRO_REDIS);
return cacheManager;
}
@Bean(name = "shiroRedisTemplate")
public RedisTemplate<Object, Object> shiroRedisTemplate() {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(secondaryRedisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new RedisObjectSerializer());
return template;
}
@Bean(name = "secondaryRedisConnectionFactory")
@DependsOn(value = "shiroProperties")
public RedisConnectionFactory secondaryRedisConnectionFactory() {
// 单机版配置
RedisStandaloneConfiguration redisStandaloneConfiguration =
new RedisStandaloneConfiguration(shiroProperties().getHost(), shiroProperties().getPort());
redisStandaloneConfiguration.setDatabase(shiroProperties().getSecondaryDatabase());
redisStandaloneConfiguration.setPassword(RedisPassword.of(shiroProperties().getPassword()));
// 集群版配置
// RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
// String[] serverArray = clusterNodes.split(",");
// Set<RedisNode> nodes = new HashSet<RedisNode>();
// for (String ipPort : serverArray) {
// String[] ipAndPort = ipPort.split(":");
// nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1])));
// }
// redisClusterConfiguration.setPassword(RedisPassword.of(password));
// redisClusterConfiguration.setClusterNodes(nodes);
// redisClusterConfiguration.setMaxRedirects(maxRedirects);
// 客户端配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();// 连接池配置
poolConfig.setMaxIdle(shiroProperties().getLettuce().getPool().getMaxIdle());
poolConfig.setMaxTotal(shiroProperties().getLettuce().getPool().getMaxActive());
poolConfig.setMaxWaitMillis(shiroProperties().getLettuce().getPool().getMaxWait().toMillis());
poolConfig.setMinIdle(shiroProperties().getLettuce().getPool().getMinIdle());
LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder()
.poolConfig(poolConfig).commandTimeout(shiroProperties().getLettuce().getShutdownTimeout()).build();
LettuceConnectionFactory redisConnectionFactory =
new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
log.info("1.初始化Redis缓存服务器(登录用户Session及Shiro缓存管理)... ...");
return redisConnectionFactory;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
*
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
@Bean
@DependsOn(value = {"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultCreator = new DefaultAdvisorAutoProxyCreator();
defaultCreator.setProxyTargetClass(true);
return defaultCreator;
}
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ShrioRedisCache<K, V> implements Cache<K, V> {
@Resource(name="shiroRedisTemplate")
private RedisTemplate<K, V> shiroRedisTemplate;
private String prefix = "shiro_redis:";
public ShrioRedisCache(RedisTemplate<K, V> shiroRedisTemplate) {
this.shiroRedisTemplate = shiroRedisTemplate;
}
public ShrioRedisCache(RedisTemplate<K, V> shiroRedisTemplate, String prefix) {
this(shiroRedisTemplate);
this.prefix = prefix;
}
@Override
public V get(K key) throws CacheException {
if (log.isDebugEnabled()) {
log.debug("Key: {}", key);
}
if (key == null) {
return null;
}
return shiroRedisTemplate.boundValueOps(getCacheKey(key)).get();
}
@Override
public V put(K key, V value) throws CacheException {
if (log.isDebugEnabled()) {
log.debug("Key: {}, value: {}", key, value);
}
if (key == null || value == null) {
return null;
}
V old = get(key);
shiroRedisTemplate.boundValueOps(getCacheKey(key)).set(value);
return old;
}
@Override
public V remove(K key) throws CacheException {
if (log.isDebugEnabled()) {
log.debug("Key: {}", key);
}
if (key == null) {
return null;
}
V old = get(key);
shiroRedisTemplate.delete(getCacheKey(key));
return old;
}
@Override
public void clear() throws CacheException {
shiroRedisTemplate.getConnectionFactory().getConnection().flushDb();
}
@Override
public int size() {
Long len = shiroRedisTemplate.getConnectionFactory().getConnection().dbSize();
return len.intValue();
}
@Override
public Set<K> keys() {
return shiroRedisTemplate.keys(getCacheKey("*"));
}
@Override
public Collection<V> values() {
Set<K> set = keys();
List<V> list = new ArrayList<V>();
for (K s : set) {
list.add(get(s));
}
return list;
}
@SuppressWarnings("unchecked")
private K getCacheKey(Object k) {
return (K) (this.prefix + k);
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
}
import org.apache.shiro.cache.AbstractCacheManager;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;
public class ShrioRedisCacheManager extends AbstractCacheManager {
private RedisTemplate<Object, Object> shiroRedisTemplate;
public ShrioRedisCacheManager(RedisTemplate<Object, Object> shiroRedisTemplate) {
this.shiroRedisTemplate = shiroRedisTemplate;
}
@Override
protected Cache<Object, Object> createCache(String name) throws CacheException {
return new ShrioRedisCache<Object, Object>(shiroRedisTemplate, name);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment