缓存

  • 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来管理缓存,设置方式有两种。
  1. 设置在SecurityManager中,最终也会设置给CachingRealm,其实真正使用CacheManager的组件也就realm和SessionDAO。