1. 程式人生 > >springboot 配置ehcache快取,通過註解定製多租戶(multiTenantId)生成快取的key,並且實現註解按照tenantId清除快取,tanant之間快取互相不影響

springboot 配置ehcache快取,通過註解定製多租戶(multiTenantId)生成快取的key,並且實現註解按照tenantId清除快取,tanant之間快取互相不影響

調研背景

    本公司有一項功能需求,由於查詢的資料太多會導致訪問時間超優化API介面,但是這不是長久之計,便決定引入快取,但是此 快取能夠實現按照不同租戶的ID號碼在同一個cacheName中去生成能識別租戶的key,而且在使用cacheEvict時候能夠清除在當前租戶在cacheName裡面所有的快取,不能清除使用者在這個cacheName裡面的快取,並開始了我的調研,和不斷的debug,檢視底層實現的程式碼,最終經過一個星期的調研,實現了這個功能,現在想分享給大家,希望對你們今後會給你們幫助和思路。

分析如何定製生成的快取key,滿足我們的要求。

    因為想用註解的方式去生成快取,@Cacheable()可以生成快取,那麼我便去研究這個註解的實現,通過檢視他的方法,我們可以看到 ,如果我們想定製key的話,那麼這個keyGenerator()是不是有什麼用處,經調查發現,這個是生成預設的key。如果用在方法上,是將方法的強求引數全部都給按照順序和值,然後返回的引數形成一個唯一的key。那此時思路就來了 ,那麼是不是可以直接在這上面定義當前租戶的tenantId,那麼就開始去動手,重寫keyGenerator()

這兩個類就是我重寫的。下面我貼出裡面的重寫的原始碼。

重寫了keyGenerator()方法,將只是生成引數key修改成前面有tenantId+simpleKey(還是以前的引數key)這樣就按照租戶生成了同一個引數的不同快取,存在於同一個CacheName 的集合下面

分析springboot快取原始碼:

    springboot如何使用配置ehcache快取,文章一搜一大把,這裡就不再贅述 。首先就開始分析原始碼:以及改造生成的key的思路:

首先可以看到,springboot通過@EnableCaching為入口開啟快取,進入註解我們可以看到@Import(CachingConfigurationSelector.Class)匯入了配置的選擇器。

由於在註解裡面預設就會宣告預設的是按照poxy代理的的方式載入模式

這邊底層添加了代理模式的配置 ,那麼我們再進入到裡面,

接著配置裡面主要是定義了cache的攔截器。我們再進入到攔截器可以發現裡面呼叫了invoke()方法,這個方法主要是實現了,若快取中存在則直接返回返回快取的方法,沒有就會去執行方法。

我們主要是看看他的父類,cacheAspectSupport這個類,然後再這個類裡面我們可以看到又很多的方法,找到了,我們需要的功能,是清除的方法,大家可以debug進來,能夠看到最終會進入到這個類裡面

cacheEvict會執行我標記的地方如果allEntries=true就會執行doClean()否則會執行下面的doEvict,那麼頓時清除快取的思想便油然而生,我們可以重寫這個方法,但是如果要重寫這個方法,那我們是不是就應該要把前面的都要重寫一遍,對噠,springboot註解就是如此之煩躁,那你既然想要定製,那你就當然別怕麻煩。但是又出現了一個問題,那你是不是註解也要換,如果你不換註解,重寫的東西太多了。所以一拍即合,開幹,直接從源頭開始重寫,下面貼出我重寫的程式碼的圖,從上到下。

首先放上我重寫的所有類,大家可以看到,從註解,到上面給大家截圖的原始碼我都重寫了,只不過都加了個字首,printSaas,其實內容都是複製過來,但是做了一些修改。我們從上到下,看看哪些修改,我會標記出來

這邊註釋掉兩行程式碼是因為,我還沒弄清這個具體是幹啥的,但是我大概瞭解是由於我換了新註解,不註釋掉這兩行的話會報錯,報沒有開啟EnableCaching,然後我跟蹤下去,是因為上面兩行程式碼也是與下圖一樣,是因為通過了EnableCacing註冊的所以會報錯。我也懶得再去重寫,太多太深了,所以對我業務沒影響我就註釋掉了

這個圖做個說明:首先我重新定義了cache攔截器,然後我重寫了下面這個方法,是因為,這裡面本來定義的是EnableCaching.class.getName,如果你不重寫,那麼容器則無法識別你的新註解,會報錯。

這是最後一張,就是為了重寫doclear()方法,主要思路是迴圈cache下面所有的key,判斷如果當前的租戶Id號與key的tenantId相等,那麼則通過key去清除。為了適應多種cacheManage我做了一些判斷,因為ehcacheCache無法轉成googleCache,因為我的程式預設是GuavaCacheManage,我也沒找到到底是怎麼預設的(希望哪位大神知道可以告知我一下)我知道他的機制是通過autoConfiguration去遍歷各種cacheManage,如果又合適的或者說再condition中匹配成功的就使用哪個cacheManager。我就是在resource下面建立了一個ehcache.xml便使用了ehcache。這一塊還是沒完全弄懂他的機制是啥,希望有知道的大神和我說一聲。

 

最後我的研究已經說完了,可能我的說法有誤,但是我確實實現了這個需求和功能,希望大神指教。