缓存
- Shiro提供了类似于Spring的Cache抽象,即它本身不实现cache,但是对cache进行了抽象,方便更换底层cache实现(如,Ehcache,Hazelcast,OSCache,Terracotta,Coherence,GigaSpaces,JBossCache)。
- Cache接口:
public interface Cache<K, V> {
//根据Key获取缓存中的值
public V get(K key) throws CacheException;
//往缓存中放入key-value,返回缓存中之前的值
public V put(K key, V value) throws CacheException;
//移除缓存中key对应的值,返回该值
public V remove(K key) throws CacheException;
//清空整个缓存
public void clear() throws CacheException;
//返回缓存大小
public int size();
//获取缓存中所有的key
public Set<K> keys();
//获取缓存中所有的value
public Collection<V> values();
}
- CacheManager接口:从接口方法来看就是用来获取cache的。
public interface CacheManager {
//根据缓存名字获取一个Cache实例,不存在则新建一个
public <K, V> Cache<K, V> getCache(String name) throws CacheException;
}
从上面来看,我们定义缓存要做两件事,一是实现Cache接口(shiro-ehcache.xml),二是实现CacheManager接口(shiro.ini中注册EhCacheManager的bean)。
Shiro数据的缓存方式分为两类,一是将数据存储到本地,一是存储到集中式存储中间件,如,redis或Memcached。若使用后者,当页面使用了大量shiro标签时(如,<shiro:hasPermission name=”admin”>),每个标签都会发起一个查询请求,那么访问一个页面将会向缓存发送大量网络请求,这回给集中缓存组件带来一定的瞬时请求压力,而且,网络查询的效率并不高。采用本地缓存则不存在这些问题。所以,如果在项目中使用了大量shiro标签,那还是采用本次缓存更合适。
- MemoryConstraintCacheManager: 本地缓存。
EhCacheManager:集中式缓存。
CacheManagerAware:用于注入CacheManager
public interface CacheManagerAware {
//注入CacheManager
void setCacheManager(CacheManager cacheManager);
}
- Shiro内部的组件DefaultSecurityManager会自动检测相应的对象(如Realm)是否实现了CacheManagerAware,并自动注入相应的CacheManager。
Realm缓存
- 即权限数据的缓存(其实还有用户身份AuthenticationInfo的缓存,不过用的比较少,暂且忽略),需要设置一个CacheManager来管理缓存,设置方式有两种。
- 设置在SecurityManager中,最终也会设置给CachingRealm,其实真正使用CacheManager的组件也就realm和SessionDAO。