天天看点

shiro缓存配置详细说明

分享知识 传递快乐

shiro缓存的两种方案:

1、ehcache-core

先在pom.xml文件中引入包:

<dependency>
  <groupId>net.sf.ehcache</groupId>
  <artifactId>ehcache-core</artifactId>
  <version>2.6.11</version>
</dependency>      

spring-ehcache.xml文件配置

<!-- 配置 Spring 的 EhCacheManagerFactoryBean -->
<bean id="cacheManagerFactoryBean" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  <property name="configLocation" value="classpath:cache/ehcache.xml" />
  <!-- <property name="shared" value="true" /> -->
</bean>

<!-- spring 封装ehcache缓存管理器 -->
<bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
  <property name="cacheManager" ref="cacheManagerFactoryBean" />
</bean>

<!-- 激活spring 缓存注解 -->
<cache:annotation-driven cache-manager="springCacheManager" />      

spring-shiro.xml文件配置

<!--安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  <!-- ......省略了其它配置 --> 
  <!--将缓存管理器,交给安全管理器(Spring提供的Ehcache实现的缓存管理器) -->
  <property name="cacheManager" ref="shiroSpringCacheManager" /> 
</bean>
<!-- 用户授权信息Cache, 采用spring-cache, 具体请查看spring-ehcache.xml -->
<bean id="shiroSpringCacheManager" class="com.xh.activiti.commons.cache.ShiroSpringCacheManager">
  <!-- cacheManager在spring-ehcache.xml里能找到 -->
  <property name="cacheManager" ref="springCacheManager" />
</bean>      

此时还要两个类

package com.xh.activiti.commons.cache;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.util.Destroyable;

/**
 * 
 * <p>Title: 使用spring-cache作为shiro缓存 缓存管理器</p>
 * <p>Description: </p>
 * 
 * @author H.Yang
 * @date 2018年3月6日
 *
 */
public class ShiroSpringCacheManager implements CacheManager, Destroyable {
  private static final Logger LOGGER = LogManager.getLogger(ShiroSpringCacheManager.class);

  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;
  }

  public <K, V> Cache<K, V> getCache(String name) throws CacheException {
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("Acquiring ShiroSpringCache instance named [" + name + "]");
    }
    org.springframework.cache.Cache cache = cacheManager.getCache(name);
    return new ShiroSpringCache<K, V>(cache);
  }

  public void destroy() throws Exception {
    cacheManager = null;
  }
}      
package com.xh.activiti.commons.cache;

import java.util.Collection;
import java.util.Collections;
import java.util.Set;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.shiro.cache.CacheException;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;

/**
 * 
 * <p>Title: 使用spring-cache作为shiro缓存</p>
 * <p>Description: </p>
 * 
 * @author H.Yang
 * @date 2018年3月6日
 * 
 * @param <K>
 * @param <V>
 */
public class ShiroSpringCache<K, V> implements org.apache.shiro.cache.Cache<K, V> {
  private static final Logger LOGGER = LogManager.getLogger(ShiroSpringCache.class);

  private final org.springframework.cache.Cache cache;

  public ShiroSpringCache(Cache cache) {
    if (cache == null) {
      throw new IllegalArgumentException("Cache argument cannot be null.");
    }
    this.cache = cache;
  }

  public V get(K key) throws CacheException {
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("Getting object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());
    }
    ValueWrapper valueWrapper = cache.get(key);
    if (valueWrapper == null) {
      if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("Element for [" + key + "] is null.");
      }
      return null;
    }
    return (V) valueWrapper.get();
  }

  public V put(K key, V value) throws CacheException {
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("Putting object in cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());
    }
    V previous = get(key);
    cache.put(key, value);
    return previous;
  }

  public V remove(K key) throws CacheException {
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("Removing object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass());
    }
    V previous = get(key);
    cache.evict(key);
    return previous;
  }

  public void clear() throws CacheException {
    if (LOGGER.isTraceEnabled()) {
      LOGGER.trace("Clearing all objects from cache [" + this.cache.getName() + "]");
    }
    cache.clear();
  }

  public int size() {
    return 0;
  }

  public Set<K> keys() {
    return Collections.emptySet();
  }

  public Collection<V> values() {
    return Collections.emptySet();
  }

  @Override
  public String toString() {
    return "ShiroSpringCache [" + this.cache.getName() + "]";
  }

}      

2、shiro-ehcache

先在pom.xml文件中引入包:

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-ehcache</artifactId>
  <version>1.4.0</version>
</dependency>      

shiro-ehcache.xml文件配置

<!-- Shiro提供的Ehcache实现的缓存管理器 -->
<!-- 配置 shiro 的 ehcache 缓存相关,这个缓存只和 Realm 相关 -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:cache/ehcache.xml"/> 
</bean>

<!-- 配置SecurityManager的管理 --> 
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> 
    <!-- ......省略了其它配置 --> 
    <property name="cacheManager" ref="cacheManager"/> 
</bean>      

附:

两者结合使用

spring-ehcache.xml文件配置

<!-- 如果有多个ehcacheManager要在bean加上p:shared="true" --><!-- Shiro提供的Ehcache实现的缓存管理器 -->
<!-- 配置 shiro 的 ehcache 缓存相关,这个缓存只和 Realm 相关 -->
<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
  <property name="cacheManager" ref="cacheManagerFactoryBean" />
</bean>

<!-- Spring提供的Ehcache实现的缓存管理器 -->
<!-- 配置 Spring 的 EhCacheManagerFactoryBean -->
<bean id="cacheManagerFactoryBean" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  <property name="configLocation" value="classpath:cache/ehcache.xml" />
  <!-- 如果有多个ehcacheManager要在bean加上p:shared="true" -->
  <!-- <property name="shared" value="true" /> -->
</bean>

<!-- spring 封装ehcache缓存管理器 -->
<bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
  <property name="cacheManager" ref="cacheManagerFactoryBean" />
</bean>


<!-- 激活spring 缓存注解 -->
<cache:annotation-driven cache-manager="springCacheManager" />      

spring-shiro.xml文件配置

<!--安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  <!-- ......省略了其它配置 --> 
  <!-- Shiro提供的Ehcache实现的缓存管理器 -->
  <property name="cacheManager" ref="shiroCacheManager" />
</bean>      

这样就不用类了。

注意:

如果创建多个CacheManager对象时报以下异常: 

Caused by: net.sf.ehcache.CacheException: Another unnamed CacheManager already exists in the same VM. Please provide unique names for each CacheManager in the config or do one of following:
1. Use one of the CacheManager.create() static factory methods to reuse same CacheManager with same name or create one if necessary
2. Shutdown the earlier cacheManager before creating new one with same name.      

解决方法:

p:shared="true"      
<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  <property name="configLocation" value="classpath:cache/ehcache.xml"/>
  <property name="shared" value="true" />
</bean>