上一篇已经解决了第一个问题,session的共享,现在我们解决第二个问题cache的共享。
先看下spring的配置文件,上一篇已经提到过了
-
<span style="font-size:18px;"><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" depends-on="userRepository,roleRepository">
-
<property name="sessionManager" ref="defaultWebSessionManager" />
-
<property name="realm" ref="shiroDbRealm" />
-
<property name="cacheManager" ref="memoryConstrainedCacheManager" />
-
</bean>
-
<bean id="memoryConstrainedCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" /></span>
这里cacheManager我们注入了shiro自定的本机内存实现的cacheManager类,当然,这肯定不满足我们集群的需要,所以我们要自己实现cacheManager类,这里我还是用了redis作为cache的存储,先创建RedisCacheManager实现类
-
<span style="font-size:18px;">package com.tgb.itoo.authority.cache;
-
-
import java.util.concurrent.ConcurrentHashMap;
-
import java.util.concurrent.ConcurrentMap;
-
-
import org.apache.shiro.cache.Cache;
-
import org.apache.shiro.cache.CacheException;
-
import org.apache.shiro.cache.CacheManager;
-
import org.slf4j.Logger;
-
import org.slf4j.LoggerFactory;
-
-
public class RedisCacheManager implements CacheManager{
-
-
private static final Logger logger = LoggerFactory
-
.getLogger(RedisCacheManager.class);
-
-
-
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
-
-
private RedisManager redisManager;
-
-
-
-
-
private String keyPrefix = "shiro_redis_cache:";
-
-
-
-
-
-
-
public String getKeyPrefix() {
-
return keyPrefix;
-
}
-
-
-
-
-
-
-
public void setKeyPrefix(String keyPrefix) {
-
this.keyPrefix = keyPrefix;
-
}
-
-
@Override
-
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
-
logger.debug("获取名称为: " + name + " 的RedisCache实例");
-
-
Cache c = caches.get(name);
-
-
if (c == null) {
-
-
-
redisManager.init();
-
-
-
c = new RedisCache<K, V>(redisManager, keyPrefix);
-
-
-
caches.put(name, c);
-
}
-
return c;
-
}
-
-
public RedisManager getRedisManager() {
-
return redisManager;
-
}
-
-
public void setRedisManager(RedisManager redisManager) {
-
this.redisManager = redisManager;
-
}
-
}
-
当然,这里仅仅是getCache,我第一次看源码时,也有这样的疑问,cache的add、remove等等方法在哪里实现呢?我们继续看看shiro的源码就会知道答案了
这个是自己relm的AuthorizingRealm中的方法
-
<span style="font-size:18px;"> protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
-
-
if (principals == null) {
-
return null;
-
}
-
-
AuthorizationInfo info = null;
-
-
if (log.isTraceEnabled()) {
-
log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
-
}
-
-
Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
-
if (cache != null) {
-
if (log.isTraceEnabled()) {
-
log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
-
}
-
Object key = getAuthorizationCacheKey(principals);
-
info = cache.get(key);
-
if (log.isTraceEnabled()) {
-
if (info == null) {
-
log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
-
} else {
-
log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
-
}
-
}
-
}
-
if (info == null) {
-
-
info = <STRONG>doGetAuthorizationInfo</STRONG>(principals);
-
-
if (info != null && cache != null) {
-
if (log.isTraceEnabled()) {
-
log.trace("Caching authorization info for principals: [" + principals + "].");
-
}
-
Object key = getAuthorizationCacheKey(principals);
-
<STRONG>cache.put</STRONG>(key, info);
-
}
-
}
-
return info;
-
}
如果大家去查查引入就知道我们自定义relm要实现一个叫做doGetAuthorizationInfo()的方法,它的作用是查询授权信息,我们注意加粗的2行,发现其实cache的put方法其实才是cache存储的核心类,其实现都在cache中,所以我们需要实现自己的cache,创建RedisCache类
最后修改spring配置文件
-
<span style="font-size:18px;">
-
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
-
<property name="realm" ref="shiroRealm"></property>
-
<property name="sessionMode" value="http"></property>
-
<property name="subjectFactory" ref="casSubjectFactory"></property>
-
-
-
-
-
<property name="cacheManager" ref="redisCacheManager" />
-
-
-
<property name="sessionManager" ref="sessionManager"></property>
-
</bean></span>
这样就完成了整个shiro集群的配置
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9399028/viewspace-2102818/
,如需转载,请注明出处,否则将追究法律责任。