shiro实例 缓存之Realm篇

来源:互联网 发布:500px知乎什么意思 编辑:程序博客网 时间:2024/06/06 01:39

Shiro 提供的 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();}

Shiro 提供的 CacheManager 接口:

public interface CacheManager {    //根据缓存名字获取一个Cache    public <K, V> Cache<K, V> getCache(String name) throws CacheException;}

Shiro 还提供了 CacheManagerAware 用于注入 CacheManager:

public interface CacheManagerAware {    //注入CacheManager    void setCacheManager(CacheManager cacheManager);}

Shiro 内部相应的组件(DefaultSecurityManager)会自动检测相应的对象(如 Realm)是否实现了 CacheManagerAware 并自动注入相应的 CacheManager。
Realm 缓存

Shiro 提供了 CachingRealm,其实现了 CacheManagerAware 接口,提供了缓存的一些基础实现;另外 AuthenticatingRealm 及 AuthorizingRealm 分别提供了对 AuthenticationInfo 和 AuthorizationInfo 信息的缓存。

spring-shiro.xml配置

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <!-- 设置安全管理器的安全数据源为自定义的 Realm -->        <property name="realm" ref="myRealm"/>        <property name="cacheManager" ref="cacheManager"/>        ...    </bean><!-- 配置缓存管理器 -->    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">        <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>    </bean> <bean id="myRealm" class="com.zm.web_shiro.realm.CustomRealm">        <!-- 配置缓存相关 -->        <!-- 启用缓存 -->        <property name="cachingEnabled" value="true"/>        <!-- 开启认证缓存-->        <property name="authenticationCachingEnabled" value="true"/>        <!-- 指定认证缓存的名字(与 ehcache.xml 中声明的相同) -->        <property name="authenticationCacheName" value="authenticationCache"/>        <!--开启授权缓存-->        <property name="authorizationCachingEnabled" value="true"/>        <!-- 指定授权缓存的名字(与 ehcache.xml 中声明的相同) -->        <property name="authorizationCacheName" value="authorizationCache"/>    </bean>

ehcache-shiro.xml

<ehcache>    <!--diskStore:缓存数据持久化的目录 地址  -->    <diskStore path="E:\cache\ehcache" />    <!--<diskStore path="java.io.tmpdir"/>--> <!-- 系统的默认临时文件路径 -->    <!--         name:缓存名称。         maxElementsInMemory:缓存最大数目         maxElementsOnDisk:硬盘最大缓存个数。          eternal:对象是否永久有效,一但设置了,timeout将不起作用。          overflowToDisk:是否保存到磁盘,当系统当机时         timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。         timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。         diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.          diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。          diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。         memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。          clearOnFlush:内存数量最大时是否清除。         memoryStoreEvictionPolicy:              Ehcache的三种清空策略;              FIFO,first in first out,这个是大家最熟的,先进先出。              LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。              LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。      -->      <defaultCache            maxElementsInMemory="10000"            maxElementsOnDisk="10000000"            eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"            overflowToDisk="false"            diskPersistent="false"            diskExpiryThreadIntervalSeconds="120"            memoryStoreEvictionPolicy="LRU"    />    <!-- 登录记录缓存 锁定10分钟 -->    <cache name="passwordRetryCache"           maxEntriesLocalHeap="2000"           eternal="false"           timeToIdleSeconds="3600"           timeToLiveSeconds="0"           overflowToDisk="false"           statistics="true">    </cache>    <!-- 并发登陆,管理会话缓存 -->    <cache name="shiro-activeSessionCache" eternal="false"           maxElementsInMemory="10000"           overflowToDisk="true"           timeToIdleSeconds="0"           timeToLiveSeconds="0"/>    <!-- 授权缓存 -->    <cache name="authenticationCache"           maxEntriesLocalHeap="2000"           eternal="false"           timeToIdleSeconds="3600"           overflowToDisk="false"           statistics="true">    </cache>    <!-- 认证缓存 -->    <cache name="authorizationCache"           maxEntriesLocalHeap="2000"           eternal="false"           timeToIdleSeconds="3600"           overflowToDisk="false"           statistics="true">    </cache></ehcache>

虽然我们在配置文件中设置了缓存能储存多久,但是当我们登出 subject.logout 时,认证和授权缓存全都是会被清除的,这里我重写了父类AuthorizingRealm 的清除方法,用来直观的学习。

@Override    protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {        Cache c = getAuthenticationCache();        int cacheSize = c.keys().size();        log.info("清除【认证】缓存之前,【认证】缓存大小:" + cacheSize);        for(Object o : c.keys()){            log.info( o + " , " + c.get(o));        }        super.clearCachedAuthenticationInfo(principals);        log.info("调用父类清除【认证】缓存之后");        for(Object o : c.keys()){            log.info( o + " , " + c.get(o));        }        // 添加下面的代码清空【认证】的缓存        //User user = (User) principals.getPrimaryPrincipal();        String username = principals.getPrimaryPrincipal().toString();        SimplePrincipalCollection spc = new SimplePrincipalCollection(username,getName());        super.clearCachedAuthenticationInfo(spc);        log.info("添加了代码清除【认证】缓存之后");        cacheSize = c.keys().size();        log.info("【认证】缓存的大小:" + c.keys().size());        if (cacheSize == 0){            log.info("说明【认证】缓存被清空了。");        }    }    @Override    protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {        Cache c = getAuthorizationCache();        int cacheSize = c.keys().size();        log.info("清除【授权】缓存之前,授权】缓存的大小:" + cacheSize);        for(Object o : c.keys()){            log.info( o + " , " + c.get(o));        }        super.clearCachedAuthorizationInfo(principals);        log.info("清除【授权】缓存之后");        cacheSize = c.keys().size();        log.info("【授权】缓存的大小:" + cacheSize);        for(Object o : c.keys()){            log.info( o + " , " + c.get(o));        }        if(cacheSize == 0){            log.info("说明【授权】缓存被清空了。");        }    }
原创粉丝点击