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

来源:http://www.cnblogs.com/huangzijian/archive/2017/04/17/6723630.html
-Advertisement-
Play Games

本文大綱 一、簡介 二、緩存的概念 三、自定義實現緩存機制 四、什麼是Ehcache 五、Ehcache怎麼用 六、Spring對緩存的支持 七、Spring+Ehcache實現 八、Spring+Shiro+Ehcache實現 九、總結 一、簡介 在項目中,用到Shiro來做驗證授權的控制。但在實 ...


本文大綱

  • 一、簡介
  • 二、緩存的概念
  • 三、自定義實現緩存機制
  • 四、什麼是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緩存,來逐步讓大家接觸起緩存的使用。對於緩存的使用,還有很多更深入的內容,這裡只做了拋磚引玉,有待大家以後的使用瞭解了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 訪問控制 public(公開的):可以在類中、子類中、類外訪問。 protected(受保護的):只能在類本身及子類中訪問。 private(私有的):只能在聲明他們的類中進行訪問,私有的類成員不能被子類或者這個類的對象實例直接訪問。 抽象類和方法 在繼承概念被應用在一些場景中,創建一個父類的實例將 ...
  • 下麵說的線性表主要是線性鏈表,這裡主要將雙向鏈表,單向鏈表迴圈鏈表等是類似的,不再累述。如果發現錯誤,還望不吝指正。 定義 線性表(linear list)是數據結構的一種,一個線性表是n個具有相同特性的數據元素的有限序列。數據元素是一個抽象的符號,其具體含義在不同的情況下一般不同。 在稍複雜的線性 ...
  • 如何個判斷集合中是否存在某個元素——contains() 1.List的contains(obj)方法 實際上,List調用contains(Object obj)方法時,會遍歷List中的每一個元素,然後再調用每個元素的equals()方法去跟contains()方法中的參數進行比較,如果有一個元 ...
  • 問題描述:一進程剛獲得三個主存塊的使用權,若該進程訪問頁面的次序是1,2,3,4,1,2,5,1,2,3,4,5。當採用LRU演算法時,發生的缺頁次數是多少? Hint:LRU(Least Recently Used)意思是近期最少使用。 這個演算法常用於頁面置換演算法中。當我們新要訪問的頁面不在主存中時 ...
  • 使用toPlainString意為返回不不待指數的字元串 與toString區別當數據的位數為0的時候,使用toString就會出現無法正的的轉化的問題。 所以在處理科學計數法是不適用toString而是toPlainString,避免偶發錯誤發生。 ...
  • 一、模塊的認識。 模塊:指的是把預先寫好的內容封裝成一個模塊,可用時直接調用,模塊又稱為庫 模塊又稱為標準庫和第三方庫。 標準庫,預設安裝好官方所公佈的庫 C:\Python35\Lib 第三方庫,是從網上下載下來需要安裝上去。C:\Python35\Lib\site-packages getpas ...
  • <!-- 占用一個節點對象 --><province> <city code="027">武漢</city> <city code="0716">荊州</city> <city code="0718">宜昌</city></province><!-- 占用第三個節點對象 --> JAVA代碼如下: ...
  • 繼承(inheritance)是面向對象編程的核心機制之一,沒有使用繼承的程式設計,就不能成為面向對象的程式設計。 1.繼承的定義 特殊類的對象擁有一般類的全部屬性與行為,稱為特殊類對一般類的繼承。一個類可以是多個一般類的特殊類,也可以從多個一般類中繼承屬性與行為,但在java語言中,不允許一個類從 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...