Springboot2集成Shiro框架(六)使用MemoryConstrainedCacheManager緩存

1、什麼是MemoryConstrainedCacheManager

我們可以查看shiro提供給我們的信息瞭解這個 MemoryConstrainedCacheManager 的相關信息,在shiro提供的CacheManager接口下,默認提供了緩存抽象類 AbstractCacheManager.class ,還提供了一個實現類 MemoryConstrainedCacheManager 來實現緩存,但是這個緩存默認是關閉的,所以,在之前的篇幅中,我們每次登錄,每次訪問權限接口都會調用自定義realm中的權限認證和身份認證兩個方法。
在這裏插入圖片描述
Memory Constrained Cache Manager 翻譯過來就是保存在內存中的緩存管理器,由於運行在jvm環境下,也可以理解爲使用jvm的內存保存數據的工具,適合在單實例使用。

  • 在官方文檔上有如下說法
    基於內存的簡單{@link CacheManager CacheManager}實現可在生產中使用
    環境。它不會導致內存泄漏,因爲它會生成{@link Cache Cache}
    {@link SoftHashMap SoftHashMap}根據運行時環境的內存自動調整大小
    限制和垃圾收集行爲。
    雖然創建的{@code Cache}實例是線程安全的,但它們不提供任何企業級功能,例如
    緩存一致性,樂觀鎖定,故障轉移或其他類似功能。有關更多企業功能,請考慮
    使用由企業級緩存產品支持的不同{@code CacheManager}實現(EhCache,
    TerraCotta,Coherence,GigaSpaces等等)

2、爲什麼要使用緩存

在之前的配置中,並沒有使用緩存,我們可以看到每次登錄或者訪問權限接口時,總會頻繁的調用我們自定義realm的身份認證和權限認證的方法,尤其是權限認證!頻繁的對數據庫進行訪問,佔用很多數據庫資源,這是我們不想看到的,使用緩存可以將一些不會經常變動的值存下來,需要時直接在緩存中取數據對比即可,無需訪問數據庫,減少數據庫資源的佔用,提高系統性能等!

3、如何使用

  1. ShiroConfig類中添加緩存管理器
    /**
     * 緩存管理器
     * @return
     */
    @Bean
    public CacheManager cacheManager() {
        MemoryConstrainedCacheManager mccm = new MemoryConstrainedCacheManager();
        return mccm;
    }
  1. 授權管理器交給securityManager
    /**
     * 注入 securityManager
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        securityManager.setRememberMeManager(rememberMeManager());
        securityManager.setCacheManager(cacheManager());//配置緩存管理器
        return securityManager;
    }
  1. 自定義realm中開啓緩存
    /**
     * 自定義身份認證 realm;
     * <p>
     * 必須寫這個類,並加上 @Bean 註解,目的是注入 MyShiroRealm, 否則會影響 MyShiroRealm類 中其他類的依賴注入
     */
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        // 設置密碼比較器
        myShiroRealm.setCredentialsMatcher(CredentialsMatcher());
        // 啓用身份驗證緩存,即緩存AuthenticationInfo信息,默認false
        myShiroRealm.setAuthenticationCachingEnabled(true);
        // 啓用授權緩存,即緩存AuthorizationInfo信息,默認false,一旦配置了緩存管理器,授權緩存默認開啓
        myShiroRealm.setAuthorizationCachingEnabled(true);
        
        return myShiroRealm;
    }

4、如何清理緩存

4.1、調用logout方法

我們發現調用logout方法可以同時清除兩種緩存,但是此方法只能清除當前用戶,並且會強制退出,實用性不強。

	Subject subject = SecurityUtils.getSubject();
	// 登出
	subject.logout();

4.2、主動清理緩存

4.2.1、部分新增緩存代碼

可以看出,我們使用的緩存保存的key是採用 principals 屬性,因此我們清除的時候只需要傳入用戶名即可!

//緩存代碼
class AuthorizingRealm{
	.........................
        if (info == null) {
            // Call template method if the info was not found in a cache
            info = doGetAuthorizationInfo(principals);
            // If the info is not null and the cache has been created, then cache the authorization info.
            if (info != null && cache != null) {
                if (log.isTraceEnabled()) {
                    log.trace("Caching authorization info for principals: [" + principals + "].");
                }
                Object key = getAuthorizationCacheKey(principals);
                cache.put(key, info);
            }
        }

4.2.2、配置主動緩存清理

  1. MyShiroRealm 類中新增下列方法

    /**
     * 重寫方法,清除當前用戶的的 授權緩存
     * @param principals
     */
    public void clearCachedAuthorizationInfo() {
        super.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

    /**
     * 重寫方法,清除當前用戶的 認證緩存
     * @param principals
     */
    public void clearCachedAuthenticationInfo() {
        super.clearCachedAuthenticationInfo(SecurityUtils.getSubject().getPrincipals());
    }
    /**
     * 清除某個用戶認證和授權緩存
     */
    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    /**
     * 自定義方法:清除所有 授權緩存
     */
    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    /**
     * 自定義方法:清除所有 認證緩存
     */
    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    /**
     * 自定義方法:清除所有的  認證緩存  和 授權緩存
     */
    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }
    
    
  1. ShiroController 新增接口
    @RequestMapping("/clear")
    public ReturnMap clear() {
        RealmSecurityManager rsm = (RealmSecurityManager)SecurityUtils.getSecurityManager();  
        MyShiroRealm realm = (MyShiroRealm)rsm.getRealms().iterator().next(); 
        realm.clearCachedAuthenticationInfo();
        realm.clearCachedAuthorizationInfo();
        System.out.println("清除成功");
        return new ReturnMap().success().data("清除成功");
    }
  1. 頁面新增清除接口按鈕在這裏插入圖片描述

5、測試

  1. 我們登錄了3次,並且訪問了很多次權限接口的情況下,下圖紅色部分爲進入認證器的次數,也可以理解爲訪問數據庫次數,只有兩次,測試成功!在這裏插入圖片描述
  2. 接着上面的測試繼續,我們點擊clear接口,並且再進行登錄和接口訪問,可以看到,每次清除完緩存之後,下次訪問必定會再次訪問數據庫,把數據寫入緩存,清除緩存測試成功!
  3. 在這裏插入圖片描述

4、源碼

  • 需要源碼可以點擊這裏獲取!
  • 另,非常感謝凌寒11童鞋分享的清除緩存代碼!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章