本例在上一節Shiro基本功能基礎上增加緩存功能,主要緩存Session、身份、權限等,對于實際應用會減少查詢資料庫次數,提升效率。Shiro為我們提供了CacheManager接口,在1.2.x版本中,提供了EhCache緩存的實作EhCacheManager和預設的MemoryConstrainedCacheManager的實作,到1.3.x版本時,增加了基于Hazelcast的分布式緩存實作HazelcastCacheManager。
通常在單應用中使用EhCache的緩存實作。在上一執行個體基礎上添加EhCache緩存,具體步驟如下:
步驟1:在classpath下添加ehcache.xml配置檔案:/META-INF/ehcache/ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">
<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,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那麼現有緩存元素中時間戳離目前時間最遠的元素将被清出緩存。
-->
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro-activeSessionCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
</ehcache>
步驟2:在ShiroConfiguration配置類中,建立緩存管理器@Bean
/**
* Shiro CacheManager 定義 Shiro 緩存管理器
*
* 需要加入到安全管理器:securityManager
* @return
*/
@Bean
public EhCacheManager ehCacheManager() {
logger.info("注入Shiro的緩存管理器-->ehCacheManager", EhCacheManager.class);
EhCacheManager cacheManager = new EhCacheManager();
cacheManager.setCacheManagerConfigFile("classpath:META-INF/ehcache/ehcache.xml");
return cacheManager;
}
步驟3:将緩存管理器注入到SecurityManager中
@Bean
public SecurityManager securityManager() {
logger.info("注入Shiro的Web過濾器-->securityManager", ShiroFilterFactoryBean.class);
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//設定Realm,用于擷取認證憑證
securityManager.setRealm(userRealm());
//注入EhCacheManager緩存管理器
securityManager.setCacheManager(ehCacheManager());
return securityManager;
}
步驟4:在realm中開啟緩存(預設是false)
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
//告訴realm,使用credentialsMatcher加密算法類來驗證密文
userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
//啟用緩存,預設false
userRealm.setCachingEnabled(true);
// 啟用身份驗證緩存,即緩存AuthenticationInfo資訊,預設false;
userRealm.setAuthenticationCachingEnabled(true);
// 緩存AuthenticationInfo資訊的緩存名稱,即配置在ehcache.xml中的cache name
userRealm.setAuthenticationCacheName("authenticationCache");
// 啟用授權緩存,即緩存AuthorizationInfo資訊,預設false;
userRealm.setAuthorizationCachingEnabled(true);
// 緩存AuthorizationInfo資訊的緩存名稱;
userRealm.setAuthorizationCacheName("authorizationCache");
return userRealm;
}
測試:
- 比如登陸後,1小時不重新整理頁面,session會自動失效(timeToIdleSeconds=”3600”)
- 前段擷取角色、權限等資訊,第一次擷取時,回去資料庫查詢(發出sql語句),在有效時間内,再次擷取時,直接從緩存中擷取。