天天看點

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>