從零到實現Shiro中Authorization和Authentication的緩存


本文大綱

  • 一、簡介
  • 二、緩存的概念
  • 三、自定義實現緩存機制
  • 四、什么是Ehcache
  • 五、Ehcache怎么用
  • 六、Spring對緩存的支持
  • 七、Spring+Ehcache實現
  • 八、Spring+Shiro+Ehcache實現
  • 九、總結

   

一、簡介

在項目中,用到Shiro來做驗證授權的控制。但在實際使用的時候,發現用戶每訪問一個功能,都會重新到UserRealm中獲取一次權限。這樣子會花費大量的系統系統。此時就想到了使用緩存,查了一下,Shiro也確實支持AuthorizationAuthentication做緩存,那就果斷使用。

但說到緩存,究竟是怎么一回事呢?這里我將從零開始向大家介紹一下緩存。由於網上已經有很多具體實現的文章了,本文內容是對緩存知識的逐步進階整理,目的是讓大家能從零開始對緩存進行了解,直到懂得如何實現Spring+Shiro+Ehcache的緩存配置。文章中不會重復網上能找到的一大堆內容,並會給出相關的參考文章給大家參考。

   

二、緩存的概念

1、緩存簡介

緩存,簡單來說,就是讓數據更接近於使用者。工作機制是:先從緩存中讀取數據,如果沒有再從慢速設備上(如數據庫)讀取實際數據(數據也會存入緩存)。

2、緩存策略

緩存中數據都有一定的生命周期,什么時候移除、什么時候到期,都有一定的講究。主要分下面三點。

2.1 移除策略

移除策略,即如果緩存滿了,從緩存中移除數據的策略;常見的有LFU、LRU、FIFO:

FIFO(First In First Out):先進先出算法,即先放入緩存的先被移除;

LRU(Least Recently Used):最久未使用算法,使用時間距離現在最久的那個被移除;

LFU(Least Frequently Used):最近最少使用算法,一定時間段內使用次數(頻率)最少的那個被移除;

2.2 TTLTime To Live

存活期,即從緩存中創建時間點開始直到它到期的一個時間段(不管在這個時間段內有沒有訪問都將過期)

2.3 TTITime To Idle

空閑期,即一個數據多久沒被訪問將從緩存中移除的時間。

3、參考資料

可參看此文的緩存簡介:http://jinnianshilongnian.iteye.com/blog/2001040

   

三、自定義實現緩存機制

1 實現步驟

實現簡單的緩存機制,通常只需實現下面四點:

  1. 確定用什么來做cache,通常使用ConcurrentHashMap鍵值對來做cache。
  2. 創建緩存管理器CacheManager,緩存管理器主要實現以下內容:
    1. 創建一個cache並進行管理
    2. 通過key來獲取value的方法
    3. 根據key更新或新增緩存中的記錄的方法
    4. 根據key來刪除緩存中一條記錄的方法
    5. 清空緩存中的所有記錄的方法
  3. Service實現類中,當查詢內容的時候,先查詢緩存中的內容,若有,則返回;若無,則查詢數據庫中的內容,同時將查詢結果加到緩存中。
  4. 在數據庫數據有更新的時候,注意調用方法更新緩存中的數據。

只要選擇好cache,和創建好CacheManager,就可以在Service中,通過創建CacheManager來管理緩存了。

2 存在問題

但我們自己做出來的緩存由於比較簡單考慮得沒那么全面,所以問題也不少,如:

  1. 與業務邏輯代碼耦合度很高,需要在Service的方法中調用CacheManager的很多邏輯,不便於維護。
  2. 程序不夠靈活,無法根據不同的條件進行緩存。
  3. 沒有完善的移除策略,需要開發人員在業務邏輯中進行控制,難以維護。
  4. 不通用,無法使用第三方提供的緩存框架。

等等。

3 參考資料

由於網上已有很多實現的文章,這里不做重復。例如可參考:

http://blog.csdn.net/fanzhanwei/article/details/44958297

   

四、什么是Ehcache

上一節是自定義緩存的實現,可以看出,自己可以做一個簡單的緩存,但是不夠完善。其實已經有很多第三方的緩存框架,有完善的機制,可以給我們使用,而ehcache就是這樣一種緩存框架。

1 Ehcache簡介

EhCache是一個純Java的進程內緩存框架,具有快速、精干等特點,也是Hibernate中默認的CacheProvider。它會把查出來的數據存儲在內存或者磁盤中,以節省查詢數據庫的壓力。

2 Ehcache使用條件

  • 比較少更新的表數據

    因為如果更新很頻繁的數據,那就沒有緩存的必要了,可能還會增加開銷呢。

  • 對數據一致性要求不高的情況

    聽說Ehcache的同步不是很完善,會造成不同服務器上的Ehcache緩存同步未必及時,這樣可能會造成用戶在獲取數據的時候不一致。

3 Ehcache使用場景

  • 頁面緩存
  • 對象緩存
  • 數據庫數據緩存

   

五、Ehcache怎么用

1 Ehcache使用步驟

使用Ehcache,基本步驟如下:

  1. 創建一個ehcache.xml的配置文件,里面會有磁盤緩存位置、緩存配置等信息。
  2. 創建CacheManager,並讀取相應的xml配置
    1. 直接CacheManager cacheManage = new CacheManager(),讀取默認配置文件。
    2. 通過靜態方法create()創建,加載默認配置。
    3. 通過newInstance()工廠方法創建,newInstance()會有幾個重載,可以傳入String、URL、InputStream等來加載配置文件。
  3. 創建Cache,可以在ehcache.xml等配置文件中配置好,也可以直接通過API創建cache,然后通過cacheManager.addCache()方法將cache加到緩存管理器中。
  4. 通過cacheManager.getCache()方法獲取Cache
  5. 創建Element對象,存放鍵值對。
  6. 將創建的Element對象存放到cache中。
  7. 通過以上步驟,就已經把緩存弄好並存了相關內容到緩存中了。要想獲得緩存中的內容,就逆向操作,先使用cache.get()Element獲取出來,接着通過Element.getObjectValue()獲取到相應的值。

2 Ehcache配置文件

關於配置文件,默認情況下會加載classpath下名為ehcache.xml的配置文件。如果加載失敗,會加載Ehcache報中的ehcache-failsafe.xml文件,這個文件中含有簡單的默認配置。

ehcache.xml配置文件中,需要了解各參數的意思,以下是一個范例:

  • name:緩存名稱。
  • maxElementsInMemory:緩存最大個數。
  • eternal:緩存中對象是否為永久的,如果是,超時設置將被忽略,對象從不過期。
  • timeToIdleSeconds:置對象在失效前的允許閑置時間(單位:秒)。僅當eternal=false對象不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大。
  • timeToLiveSeconds:緩存數據的生存時間(TTL),也就是一個元素從構建到消亡的最大時間間隔值,這只能在元素不是永久駐留時有效,如果該值是0就意味着元素可以停頓無窮長的時間。
  • maxEntriesLocalDisk:當內存中對象數量達到maxElementsInMemory時,Ehcache將會對象寫到磁盤中。
  • overflowToDisk:內存不足時,是否啟用磁盤緩存。
  • diskSpoolBufferSizeMB:這個參數設置DiskStore(磁盤緩存)的緩存區大小。默認是30MB。每個Cache都應該有自己的一個緩沖區。
  • maxElementsOnDisk:硬盤最大緩存個數。
  • diskPersistent:是否在VM重啟時存儲硬盤的緩存數據。默認值是false
  • diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認是120秒。
  • memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。默認策略是LRU(最近最少使用)。你可以設置為FIFO(先進先出)或是LFU(較少使用)。
  • clearOnFlush:內存數量最大時是否清除。

3 參考資料

具體例子可參考此網站:http://www.cnblogs.com/jingmoxukong/p/5975994.html

   

六、Spring對緩存的支持

1 Spring配置

Spring本身有對緩存方案的簡單實現,可通過注釋驅動來實現緩存機制。緩存中,最重要的兩個概念就是CacheManagerCacheSpring中的實現分別是:

  • CacheManagerorg.springframework.cache.support.SimpleCacheManager
  • Cacheorg.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean

另外加上緩存的注解驅動配置:<cache:annotation-driven />

所以關鍵的spring xml配置文件如下:

2 重要注釋

Spring緩存中,關鍵是在方法中增加@Cacheable@CachePut@CacheEvict三個注釋,然后方法內注意實現業務邏輯就好,無需像《第二部分:自定義實現緩存機制》那樣子要參雜很多的緩存管理邏輯,這就是第三方緩存框架的一大好處。實際上Spring是通過Spring AOP,在方法的調用前后,分別攔截參數和返回值,來實現緩存的錄入的。關於上面上個注釋的作用如下:

  • @Cacheable:主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存。
  • @CachePut:主要針對方法配置,能夠根據方法的請求參數對其結果進行緩存,和@Cacheable不同的是,它每次都會觸發真實方法的調用。
  • @CacheEvict,主要針對方法配置,能夠根據一定的條件對緩存進行清空。

具體例子可參考此網站:https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/

   

七、Spring+Ehcache實現

Spring cache能滿足一些基本的緩存需求,但如果需求復雜了,用戶量上去了,或者性能要求高了,Spring cache就估計難以支持了。因為它不支持高可用性,也不具備持久化數據的能力,這個時候就需要用到第三方的緩存方案,但還是用Spring的API,代碼無需改動。這就是最理想的狀態了,而Spring也支持這一點。

要配置實用Ehcache,主要改動Springxml配置文件,將cacheManager這個bean的具體實現由org.springframework.cache.support.SimpleCacheManager改為org.springframework.cache.ehcache.EhCacheCacheManager,並引用org.springframework.cache.ehcache.EhCacheManagerFactoryBean這個bean。此兩個類的作用:

org.springframework.cache.ehcache.EhCacheManagerFactoryBean:加載Ehcache配置文件。

org.springframework.cache.ehcache.EhCacheCacheManager:支持net.sf.ehcache.CacheManager

配置文件如下:

具體例子可參考此網站:http://www.cnblogs.com/jingmoxukong/p/5975994.html

   

八、Spring+Shiro+Ehcache實現

1 配置cacheManager

如果要集成Shiro,這里又得在Springxml配置文件中修改一下cacheManager的實現類,將其改為org.apache.shiro.cache.ehcache.EhCacheManager。如下:

 

<!-- 緩存管理器 使用Ehcache實現 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
  <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean>

 

這樣就可以使用適合shiroEhcacheCacheManager了。

2 配置Realm

修改Realmbean,指定其cache相關屬性的值,如下:

<!-- Realm實現 -->
<bean id="userRealm" class="com.huangzijian.realm.UserRealm">
  <property name="cachingEnabled" value="true"/>
  <property name="authenticationCachingEnabled" value="true"/>
  <property name="authenticationCacheName" value="authenticationCache"/>
  <property name="authorizationCachingEnabled" value="true"/>
  <property name="authorizationCacheName" value="authorizationCache"/>
</bean>

注意此處的cacheName,就是指在Ehcache中配置的cache,也就是通常在ehcache.xml中定義的cacahe

3 配置securityManager

需要在securityManager中配置cacheManager屬性,引用配好的cacheManager,如下:

<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
  <property name="realms">
    <list>
      <
ref bean="userRealm"/>
    </
list>   </property>   <property name="sessionManager" ref="sessionManager"/>   <property name="cacheManager" ref="cacheManager"/> </bean>

經過上面三步,即可激活ShiroAuthenticationAuthorization的緩存機制,從而不必要每次都讀取數據庫來確定該人員的角色之類的,極大的節省了資源。

   

九、總結

通過上述一步一步的進階,相信大家都可以實現自己想要的緩存了。本文是通過要實現shiro中的AuthorizationAuthentication緩存,來逐步讓大家接觸起緩存的使用。對於緩存的使用,還有很多更深入的內容,這里只做了拋磚引玉,有待大家以后的使用了解了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM