项目要求直接在配置文件中可切换redis单节点和集群模式,以前依赖shiro-redis开源项目,虽然可切换但有点麻烦,研究借助spring-data-redis直接集成。
spring:
redis:
database: 0
host: redis
password:
port: 6379
timeout: 60000
#cluster:
#nodes: 127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005
pool:
max-active: 80
max-idle: 8
max-wait: -1
min-idle: 0
上面是单节点配置,集群去掉注释cluster,及nodes.如下:
spring:
redis:
database: 0
# host: redis
password:
# port: 6379
timeout: 60000
cluster:
nodes: 127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005
pool:
max-active: 80
max-idle: 8
max-wait: -1
min-idle: 0
上述host及port也可不注释,优先使用集群模式。
@Configuration
public class ShiroConfig {
@Autowired
private RedisTemplate redisTemplate;
/**
* 自己实现
* @title systemCredentilsMatch
* @description 密码验证器
* @param
* @return SimpleCredentialsMatcher 返回类型
* @throws
*/
@Bean
public SimpleCredentialsMatcher systemCredentilsMatch(){
return new SystemCredentilsMatch();
}
/**
* 自己的realm
* @title systemShiroRealms
* @description 身份认证以及授权
* @param
* @return SystemShiroRealms 返回类型
* @throws
*/
@Bean
public SystemShiroRealms systemShiroRealms(){
SystemShiroRealms systemShiroRealms = new SystemShiroRealms();
systemShiroRealms.setCredentialsMatcher(systemCredentilsMatch());
return systemShiroRealms;
}
/**
*
* @title systemSessionManager
* @description session管理器设置
* @param
* @return SystemSessionManager 返回类型
* @throws
*/
@Bean
public SystemSessionManager systemSessionManager(){
SystemSessionManager systemSessionManager = new SystemSessionManager();
systemSessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
return systemSessionManager;
}
/**
* 实现shiroRedisCacheManager
* @author
* @date 18-11-12 下午4:45
* @param [template]
* @throws
* @return ShiroRedisCacheManager
*
*/
private ShiroRedisCacheManager cacheManager(){
return new ShiroRedisCacheManager(redisTemplate);
}
/**
*
* @title securityManager
* @description shiro安全管理器配置
* @param
* @return SecurityManager 返回类型
* @throws
*/
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setCacheManager(cacheManager());
securityManager.setSessionManager(systemSessionManager());
securityManager.setRealm(systemShiroRealms());
return securityManager;
}
/**
*
* @title shiroFilterFactoryBean
* @description Shiro核心过滤器配置
* @param
* @return ShiroFilterFactoryBean 返回类型
* @throws
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/ai/**", "authc");
filterChainDefinitionMap.put("/ai/*", "authc");
filterChainDefinitionMap.put("/druid/**","anon");
filterChainDefinitionMap.put("/**", "anon");
//配置Shiro默认跳转至登录地址时,将以json格式数据返回
shiroFilterFactoryBean.setLoginUrl("/unAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
*
* @title defaultAdvisorAutoProxyCreator
* @description 开启自动代理
* @param
* @return DefaultAdvisorAutoProxyCreator 返回类型
* @throws
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
return proxyCreator;
}
/**
*
* @title authorizationAttributeSourceAdvisor
* @description 开启权限认证
* @param
* @return AuthorizationAttributeSourceAdvisor 返回类型
* @throws
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
本类已在上面的shiro配置中。给出实现:
public class ShiroRedisCacheManager extends AbstractCacheManager {
private RedisTemplate<byte[],byte[]> redisTemplate;
public ShiroRedisCacheManager(RedisTemplate redisTemplate){
this.redisTemplate = redisTemplate;
}
@Override
protected Cache createCache(String name) throws CacheException {
return new ShiroRedisCache(redisTemplate,name);
}
}
class ShiroRedisCache<K,V> implements Cache<K,V> {
private RedisTemplate redisTemplate;
private String prefix = "random_shiro_redis";
public String getPrefix() {
return prefix+":";
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public ShiroRedisCache(RedisTemplate redisTemplate){
this.redisTemplate = redisTemplate;
}
public ShiroRedisCache(RedisTemplate redisTemplate,String prefix){
this(redisTemplate);
this.prefix = prefix;
}
@Override
public V get(K k) throws CacheException {
if (k == null) {
return null;
}
byte[] bytes = getBytesKey(k);
return (V)redisTemplate.opsForValue().get(bytes);
}
@Override
public V put(K k, V v) throws CacheException {
if (k== null || v == null) {
return null;
}
byte[] bytes = getBytesKey(k);
redisTemplate.opsForValue().set(bytes, v);
return v;
}
@Override
public V remove(K k) throws CacheException {
if(k==null){
return null;
}
byte[] bytes =getBytesKey(k);
V v = (V)redisTemplate.opsForValue().get(bytes);
redisTemplate.delete(bytes);
return v;
}
@Override
public void clear() throws CacheException {
redisTemplate.getConnectionFactory().getConnection().flushDb();
}
@Override
public int size() {
return redisTemplate.getConnectionFactory().getConnection().dbSize().intValue();
}
@Override
public Set<K> keys() {
byte[] bytes = (getPrefix()+"*").getBytes();
Set<byte[]> keys = redisTemplate.keys(bytes);
Set<K> sets = new HashSet<>();
for (byte[] key:keys) {
sets.add((K)key);
}
return sets;
}
@Override
public Collection<V> values() {
Set<K> keys = keys();
List<V> values = new ArrayList<>(keys.size());
for(K k :keys){
values.add(get(k));
}
return values;
}
private byte[] getBytesKey(K key){
if(key instanceof String){
String prekey = this.getPrefix() + key;
return prekey.getBytes();
}else {
return SerializeUtil.serialize(key);
}
}
}
上述集成完毕,操作redis可使用,可使用RedisTemplate.这里已准备好了包装类RedisTemplateUtils,功能十分完善,有需要请留言,当然也可在网上搜索。