Shiro缓存使用Redis、Ehcache、自带的MpCache实现的三种方式实例

第一种:使用Redis做缓存,将数据存储到redis数据库中

第一步:在项目里面引入redis,配置文件如下:

配置文件:spring_shiro_redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/cache
       http://www.springframework.org/schema/cache/spring-cache.xsd">
      <description>spring-redis-cache配置文件</description>
<!-- ###############################-Redis-########################################### -->
    <!-- 配置redis和spring 的整合 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxTotal}" />
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxWaitMillis" value="${redis.maxWaitMills}" />
        <!-- <property name="testOnBorrow" value="${redis.pool.testOnBorrow}" /> -->
    </bean>
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.masterHost}" />
        <property name="port" value="${redis.masterPort}" />
        <property name="timeout" value="${redis.timeout}" />
        <property name="password" value="${redis.masterPassword}" />
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean>
    <bean id="template" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <!-- 开启事务 -->
        <property name="enableTransactionSupport" value="true" />
        <!-- 序列化策略 推荐使用StringRedisSerializer -->
        <!--  <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property> -->
        <!-- <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property> -->
        <!--<property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property> -->
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
        </property>
    </bean>
    <!--spring cache-->
    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
          c:redisOperations-ref="template">
        <!-- 默认缓存10分钟 -->
        <property name="defaultExpiration" value="600"/>
        <property name="usePrefix" value="true"/>
        <!-- cacheName 缓存超时配置,半小时,一小时,一天 -->
        <property name="expires">
            <map key-type="java.lang.String" value-type="java.lang.Long">
                <entry key="halfHour" value="1800"/>
                <entry key="hour" value="3600"/>
                <entry key="oneDay" value="86400"/>
                <!-- shiro cache keys 对缓存的配置 -->
                <entry key="authorizationCache" value="1800"/>
                <entry key="authenticationCache" value="1800"/>
                <entry key="activeSessionCache" value="1800"/>
            </map>
        </property>
    </bean>
    <!-- cache注解,和spring-ehcache.xml中的只能使用一个 -->
    <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
</beans>

redis的配置文件redis.properties:

#Reids config
#最大能够保持活动的对象数
redis.maxIdle=10
redis.maxTotal=100
#当池内没有返回对象时最大等待时间
redis.maxWaitMills=1000
#超时时间
redis.timeout=1000
#当调用borrow Object方法时,是否进行有效性检查
redis.pool.testOnBorrow=true
#redis-master
redis.masterHost=192.168.206.128
redis.masterPort=6379
redis.masterPassword=1234

下面是spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd"
    default-lazy-init="true">
    <description>Spring-shiro配置文件</description>
     <!--配置安全管理器-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--设置自定义Realm-->
        <property name="realm" ref="myRealm"/>
        <!--将缓存管理器,交给安全管理器-->
        <property name="cacheManager" ref="shiroSpringCacheManager"/>
        <!-- 记住密码管理 -->
        <property name="rememberMeManager" ref="rememberMeManager"/>
        <property name="sessionManager" ref="sessionManager"/>
    </bean>
    <!-- 自定义realm -->
    <bean id = "myRealm" class="com.dzf.shiro.MyRealm">
        <property name="cacheManager" ref="shiroSpringCacheManager"/>
        <property name="credentialsMatcher" ref="myCredentialsMatcher"/>
        <!-- 打开缓存 -->
        <property name="cachingEnabled" value="true"/>
        <!-- 打开身份认证缓存 -->
        <property name="authenticationCachingEnabled" value="true"/>
        <!-- 打开授权缓存 -->
        <property name="authorizationCachingEnabled" value="true"/>
        <!-- 缓存AuthenticationInfo信息的缓存名称 --> 
        <property name="authenticationCacheName" value="authenticationCache"/>
        <!-- 缓存AuthorizationInfo信息的缓存名称 -->
        <property name="authorizationCacheName" value="authorizationCache"/>
    </bean>
    <!-- 配置自定义缓存管理器,中引入redis缓存管理器 -->
    <bean id = "shiroSpringCacheManager" class="com.dzf.shiro.ShiroSpringCacheManager">
        <property name="cacheManager" ref="cacheManager"/>
    </bean>
     <!-- 密码错误5次锁定半小时 -->
    <bean id="myCredentialsMatcher" class="com.dzf.shiro.MyCredentialsMatcher">
        <property name="cacheManager" ref="shiroSpringCacheManager"/>
        <property name="limitCacheName" value="halfHour"/>
        <property name="passwordHash" ref="passwordHash"/>
    </bean>
    <bean id = "passwordHash"  class="com.dzf.shiro.PasswordHash">
        <!-- 使用MD5 -->
        <property name="hashAlgorithm" value="md5" />
        <!-- 加密5次 -->
        <property name="hashIterations" value="2"/>
    </bean>
     <!-- 记住密码Cookie -->
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
            <!-- cookie的名字 -->
        <constructor-arg value="rememberMe"/>
        <property name="httpOnly" value="true"/>
        <!-- 7天,-->
        <property name="maxAge" value="604800"/>
    </bean>
    <!-- sesisonCookie 设置  -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
            <!-- cookie的名字 -->
        <constructor-arg value="sessionIdCookie"/>
        <property name="httpOnly" value="true"/>
        <!-- 30分钟  单位是秒-->
        <property name="maxAge" value="1800"/>
    </bean>   
    <!-- rememberMe管理器,cipherKey生成见{@code Base64Test.java} -->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('5aaC5qKm5oqA5pyvAAAAAA==')}"/>
        <property name="cookie" ref="rememberMeCookie"/>  
    </bean>
     <!-- 会话管理器 -->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!-- 设置全局会话超时时间 半小时  单位是毫秒-->
        <property name="globalSessionTimeout" value="1800000"/>
        <!-- url上带sessionId 默认为true -->
        <property name="sessionIdUrlRewritingEnabled" value="false"/>
        <property name="sessionIdCookie" ref="sessionIdCookie"/>
        <property name="sessionDAO" ref="sessionDAO"/>
    </bean>
    
    <!-- 会话DAO 用于会话的CRUD -->
    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
        <!-- Session缓存名字,配置30分钟过期 -->
        <property name="activeSessionsCacheName" value="activeSessionCache"/>
        <property name="cacheManager" ref="shiroSpringCacheManager"/>
    </bean>
    <!-- Shiro Filter -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 安全管理器 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 默认的登陆访问url -->
        <property name="loginUrl" value="/login.jsp"/>
        <!-- 登陆成功后跳转的url -->
        <!-- <property name="successUrl" value="/index.jsp"/> -->
        <!-- 没有权限跳转的url -->
        <property name="unauthorizedUrl" value="/unauth.jsp"/>
        <property name="filterChainDefinitions">
            <value>
                <!-- 
                    anon  不需要认证
                    authc 需要认证
                    user  验证通过或RememberMe登录的都可以
                -->
                /commons/** = anon
                /static/** = anon
                /user/login = anon
                /user/toLogin= anon
                /user/register = anon
                /register.jsp = anon
                /** = authc
            </value>
        </property>
    </bean>
    
    <!-- 静态注入,相当于调用SecurityUtils.setSecurityManager(securityManager) -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
        <property name="arguments" ref="securityManager"/>
    </bean>
    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>

第二步:定义自己的CacheManager

package com.dzf.shiro;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.util.Destroyable;
/**
 * <p> 自定义cacheManage 扩张shiro里面的缓存 使用reids作缓存 </p>
 * <description>
 *  引入自己定义的CacheManager
 *  关于CacheManager的配置文件在spring-redis-cache.xml中
 * </description>
 * @author xxxx
 * @date 2018年2月3日
 * @time 14:01:53
 */

public class ShiroSpringCacheManager implements CacheManager ,Destroyable{

    private org.springframework.cache.CacheManager cacheManager;

    public org.springframework.cache.CacheManager getCacheManager() {
        return cacheManager;
    }

    public void setCacheManager(org.springframework.cache.CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    @Override
    public void destroy() throws Exception {
        cacheManager = null;
    }

    @Override
    public <K, V> Cache<K, V> getCache(String name)  {
        if (name == null ){
            return null;
        }
        return new ShiroSpringCache<K,V>(name,getCacheManager());
    }


}

定义自己实现的Cache,实现了Shiro包里的Cache

package com.dzf.shiro;
 
 import org.apache.shiro.cache.CacheException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cache.Cache;
 import org.springframework.cache.Cache.ValueWrapper;
 import org.springframework.cache.CacheManager;
 
 import java.util.Collection;
 import java.util.Set;
 
 /**
  * <p> 自定义缓存 将数据存入到redis中 </p>
  * @author xxx
  * @date 2018年2月1日
  * @time 22:32:11
  * @param <K>
  * @param <V>
  */
 @SuppressWarnings("unchecked")
 public class ShiroSpringCache<K,V> implements org.apache.shiro.cache.Cache<K, V>{
     private static final Logger log = LoggerFactory.getLogger(ShiroSpringCache.class);
     private CacheManager cacheManager;
     private Cache cache;
 //    private RedisCache cache2;
     public ShiroSpringCache(String name, CacheManager cacheManager) {
         if(name==null || cacheManager==null){
             throw new IllegalArgumentException("cacheManager or CacheName cannot be null.");
         }
         this.cacheManager = cacheManager;
         //这里首先是从父类中获取这个cache,如果没有会创建一个redisCache,初始化这个redisCache的时候
         //会设置它的过期时间如果没有配置过这个缓存的,那么默认的缓存时间是为0的,如果配置了,就会把配置的时间赋予给这个RedisCache
         //如果从缓存的过期时间为0,就表示这个RedisCache不存在了,这个redisCache实现了spring中的cache
         this.cache= cacheManager.getCache(name);
     }
     @Override
     public V get(K key) throws CacheException {
         log.info("从缓存中获取key为{}的缓存信息",key);
         if(key == null){
             return null;
         }
         ValueWrapper valueWrapper = cache.get(key);
         if(valueWrapper==null){
             return null;
         }
         return (V) valueWrapper.get();
     }
 
     @Override
     public V put(K key, V value) throws CacheException {
         log.info("创建新的缓存,信息为:{}={}",key,value);
         cache.put(key, value);
         return get(key);
     }
 
     @Override
     public V remove(K key) throws CacheException {
         log.info("干掉key为{}的缓存",key);
         V v = get(key);
         cache.evict(key);//干掉这个名字为key的缓存
         return v;
     }
 
     @Override
     public void clear() throws CacheException {
         log.info("清空所有的缓存");
         cache.clear();
     }
 
     @Override
     public int size() {
         return cacheManager.getCacheNames().size();
     }
 
     /**
      * 获取缓存中所的key值
      */
     @Override
     public Set<K> keys() {
         return (Set<K>) cacheManager.getCacheNames();
     }
 
     /**
      * 获取缓存中所有的values值
      */
     @Override
     public Collection<V> values() {
         return (Collection<V>) cache.get(cacheManager.getCacheNames()).get();
     }
 
     @Override
     public String toString() {
         return "ShiroSpringCache [cache=" + cache + "]";
     }
 }

我来稍微解释下这个自定义ShiroSpringCache类中的CacheManager,这个是CacheManager其实就是RedisCacheManager,我们通过getter和setter注入过,RedisCacheManager是CacheManager的实现类.自己跟着源码看下去,一看就可以看的懂。到此为止,使用redis做缓存,和spring的集成就完成了。注意:需要使用的缓存只需要在spring_shiro_redis.xml中配置就行了,放入缓存中的对象需要实现序列号接口

第二种:使用Ehcache做缓存,可以将数据存储到磁盘中,也可以存到内存中

同样需要配置文件:ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" dynamicConfig="false">
    <diskStore path="java.io.tmpdir"/>
    <!--授权信息缓存-->
    <cache name="authorizationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="1800"
           timeToLiveSeconds="1800"
           overflowToDisk="false"
           statistics="true">
    </cache>
<!--身份信息缓存-->
    <cache name="authenticationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="1800"
           timeToLiveSeconds="1800"
           overflowToDisk="false"
           statistics="true">
    </cache>
<!--session缓存-->
    <cache name="activeSessionCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="1800"
           timeToLiveSeconds="1800"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <!-- 缓存半小时 -->
    <cache name="halfHour"
           maxElementsInMemory="10000"
           maxElementsOnDisk="100000"
           eternal="false"
           timeToIdleSeconds="1800"
           timeToLiveSeconds="1800"
           overflowToDisk="false"
           diskPersistent="false" />

    <!-- 缓存一小时 -->
    <cache name="hour"
           maxElementsInMemory="10000"
           maxElementsOnDisk="100000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="3600"
           overflowToDisk="false"
           diskPersistent="false" />

    <!-- 缓存一天 -->
    <cache name="oneDay"
           maxElementsInMemory="10000"
           maxElementsOnDisk="100000"
           eternal="false"
           timeToIdleSeconds="86400"
           timeToLiveSeconds="86400"
           overflowToDisk="false"
           diskPersistent="false" />

    <!--
        name:缓存名称。
        maxElementsInMemory:缓存最大个数。
        eternal:对象是否永久有效,一但设置了,timeout将不起作用。
        timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
        timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
        overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
        diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
        maxElementsOnDisk:硬盘最大缓存个数。
        diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
        diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
        memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
        clearOnFlush:内存数量最大时是否清除。
    -->
    <defaultCache name="defaultCache"
                  maxElementsInMemory="10000"
                  eternal="false"
                  timeToIdleSeconds="600"
                  timeToLiveSeconds="600"
                  overflowToDisk="false"
                  maxElementsOnDisk="100000"
                  diskPersistent="false"
                  diskExpiryThreadIntervalSeconds="120"
                  memoryStoreEvictionPolicy="LRU"/>

</ehcache>

spring和ehcache集成的配置文件:spring_ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/cache
       http://www.springframework.org/schema/cache/spring-cache.xsd">
    <!-- Spring提供的基于的Ehcache实现的缓存管理器 -->
    <!-- 如果有多个ehcacheManager要在bean加上p:shared="true" -->
    <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
        <property name="configLocation" value="classpath:ehcache.xml"/>
    </bean>
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="ehcacheManager"/>
        <property name="transactionAware" value="true"/>
    </bean>
    <!-- cache注解,和spring-redis.xml中的只能使用一个 -->
    <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
</beans>

第三种:使用MemoryConstrainedCacheManager这个缓存管理器,将数据缓存到内存中去

解释:Shiro已经为我们编写了一套缓存的实现,那就是MpCache,是使用Map实现的,有兴趣的可以去看源码

怎么使用这个shiro已经为我们实现好的缓存,是非常容易的。

在上面的spring-shiro.xml中, <!-- 配置自定义缓存管理器,中引入redis缓存管理器 -->:

<bean id = "shiroSpringCacheManager" class="com.dzf.shiro.ShiroSpringCacheManager">
        <property name="cacheManager" ref="cacheManager"/>

只需要把这个改为下面这句:

<!-- 配置shiro自带的缓存管理器 -->
     <bean id = "shiroSpringCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/>

参考链接:Shiro缓存使用Redis、Ehcache、自带的MpCache实现的三种方式实例

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值