-
-
Save guozi/f7fd3da0dd56bdde5587aa06b247e60c to your computer and use it in GitHub Desktop.
Spring Boot 2 + Spring Session 2 + Shiro 1.4 + Redis(Lettuce) Config
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#缓存服务器 | |
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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