1. 程式人生 > >springmvc redis @Cacheable擴充套件(一)

springmvc redis @Cacheable擴充套件(一)

springmvc 中有自帶的cache處理模組,可以是方法級別的快取處理,那麼在實際使用中,很可能自己造輪子,因為實際中永遠會有更奇怪的需求點。比如: **1** `清除快取時候,能模糊的進行刪除` **2** `針對不同的key,設定不同的過期時間` 這2個是有些麻煩的需求,當然針對快取內容,設定 key(這個 key 的確定)更讓人難受,不好取捨,需要有一定的開發經驗,否則只能不停的修改。 我們先集中處理第一個問題,模糊刪除 > * 1.查詢方案 > * 2.檢視低版本redis實現 > * 3.具體處理方式 ------ ## 明確問題,查詢方案 可能網上有不少的解決方案 > 1. 直接重寫 https://blog.csdn.net/Crystalqy/article/details/110681684 > 2. spring 5 + 版本的 https://my.oschina.net/u/220938/blog/3196609 > 3. 具有啟發性的 https://blog.csdn.net/yali_aini/article/details/89923548 #### 1. 首先我們從網上找到對應的修改的code,真的就是拿來就能用的那種,然後發現有2個function沒有,然後就發現你是低版本,然後就沒然後了。。 ```python 4.2.2.RELEASE
1.8.2 1.7.21 2.8.2
``` #### 2. 根據第三個,可以看到,基於 redis template 的快取處理,是有模糊處理的方法的,也就是說,可以做模糊處理。 #### 3. 檢視 spring 低版本 4.2.2 版本的 cache 的redis 類,進行簡單的 `仿做`。 ------ ## 檢視低版本redis實現 因為使用springmvc時候,都會對 redis 進行配置,設定 ttl 等引數,那麼,點進去看原始碼,就會發現 `CustomizedRedisCacheManager` 和 `CustomizeRedisCache` ,和 高版本的名字很像,那麼仔細看看,發現 CustomizeRedisCache 就是需要改造的。 ```python public void evict(RedisCacheElement element) public void evict(Object key) ``` 這2個函式。很可以,2個檔案粘貼出來,直接做成注入,發現就直接可以在 @Cacheable 的時候斷點看了。 這2個就是在刪除快取時候使用的。 ------ ## 改造一波 >
程式碼進行了刪減,需要修改後的,可以聯絡我 CustomizedRedisCacheManager ```java /** * CustomizedRedisCacheManager * * @desc 重新定義 oldcache 的 處理方式 */ public class CustomizedRedisCacheManager extends RedisCacheManager { protected RedisOperations getRedisOperations() { return this.redisOperations; } protected RedisCachePrefix getCachePrefix() { return this.cachePrefix; } protected boolean isUsePrefix() { return this.usePrefix; } public void afterPropertiesSet() { if (!CollectionUtils.isEmpty(this.configuredCacheNames)) { Iterator var1 = this.configuredCacheNames.iterator(); while (var1.hasNext()) { String cacheName = (String) var1.next(); this.createAndAddCache(cacheName); } this.configuredCacheNames.clear(); } super.afterPropertiesSet(); } protected Cache decorateCache(Cache cache) { return this.isCacheAlreadyDecorated(cache) ? cache : super.decorateCache(cache); } protected boolean isCacheAlreadyDecorated(Cache cache) { return this.isTransactionAware() && cache instanceof TransactionAwareCacheDecorator; } } ``` CustomizeRedisCache ```java /** * RedisCacheResolver * * @desc springCache 的過載 */ public class CustomizeRedisCache extends RedisCache { private final RedisOperations redisOperations; private final CustomizeRedisCache.RedisCacheMetadata cacheMetadata; private final CacheValueAccessor cacheValueAccessor; public CustomizeRedisCache(String name, byte[] prefix, RedisOperations redisOperations, long expiration) { super(name, prefix, redisOperations, expiration); Assert.hasText(name, "non-empty cache name is required"); this.cacheMetadata = new CustomizeRedisCache.RedisCacheMetadata(name, prefix); this.cacheMetadata.setDefaultExpiration(expiration); this.redisOperations = redisOperations; this.cacheValueAccessor = new CustomizeRedisCache.CacheValueAccessor(redisOperations.getValueSerializer()); } public T get(Object key, Class type) { ValueWrapper wrapper = this.get(key); return wrapper == null ? null : (T) wrapper.get(); } public ValueWrapper get(Object key) { return this.get((new RedisCacheKey(key)).usePrefix(this.cacheMetadata.getKeyPrefix()).withKeySerializer(this.redisOperations.getKeySerializer())); } /** * 重點處理,進行重寫 * * @param key */ public void evict(Object key) { if(key instanceof String){ String keyString=key.toString(); if(StringUtils.endsWith(keyString,"*")){ // evictLikePrefix(this.cacheMetadata.cacheName + keyString); evictLikePrefix(keyString); return; } if(StringUtils.startsWith(keyString,"*")){ // evictLikePrefix(this.cacheMetadata.cacheName + keyString); evictLikePrefix(keyString); return; } } // 原始 RedisCacheElement redisCacheElement = new RedisCacheElement((new RedisCacheKey(key)).usePrefix(this.cacheMetadata.getKeyPrefix()).withKeySerializer(this.redisOperations.getKeySerializer()), (Object) null); this.evict(redisCacheElement); } public void evict(RedisCacheElement element) { Assert.notNull(element, "Element must not be null!"); this.redisOperations.execute(new CustomizeRedisCache.RedisCacheEvictCallback(new CustomizeRedisCache.BinaryRedisCacheElement(element, this.cacheValueAccessor), this.cacheMetadata)); } /** * 進行模糊處理 key * * @param key */ public void evictLikePrefix(Object key){ Set keys = this.redisOperations.keys(key); if(keys != null && keys.size() > 0){ for(Object k : keys){ RedisCacheElement redisCacheElement = new RedisCacheElement((new RedisCacheKey(k)).usePrefix(this.cacheMetadata.getKeyPrefix()).withKeySerializer(this.redisOperations.getKeySerializer()), (Object) null); this.evict(redisCacheElement); } } } public void clear() { this.redisOperations.execute((RedisCallback) (this.cacheMetadata.usesKeyPrefix() ? new CustomizeRedisCache.RedisCacheCleanByPrefixCallback(this.cacheMetadata) : new CustomizeRedisCache.RedisCacheCleanByKeysCallback(this.cacheMetadata))); } public String getName() { return this.cacheMetadata.getCacheName(); } public Object getNativeCache() { return this.redisOperations; } private ValueWrapper toWrapper(Object value) { return value != null ? new SimpleValueWrapper(value) : null; } } ``` ----------------- > 可以關注來獲取對應的原始碼 ![file-list](https://img2020.cnblogs.com/blog/714390/202103/714390-20210307165722163-1848014