zoukankan      html  css  js  c++  java
  • 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没有,然后就发现你是低版本,然后就没然后了。。

        <properties>
            <org.springframework-version>4.2.2.RELEASE</org.springframework-version>
            <org.aspectj-version>1.8.2</org.aspectj-version>
            <org.slf4j-version>1.7.21</org.slf4j-version>
            <org.log4j2-version>2.8.2</org.log4j2-version>
        </properties>
    

    2. 根据第三个,可以看到,基于 redis template 的缓存处理,是有模糊处理的方法的,也就是说,可以做模糊处理。

    3. 查看 spring 低版本 4.2.2 版本的 cache 的redis 类,进行简单的 仿做


    查看低版本redis实现

    因为使用springmvc时候,都会对 redis 进行配置,设置 ttl 等参数,那么,点进去看源码,就会发现
    CustomizedRedisCacheManagerCustomizeRedisCache ,和 高版本的名字很像,那么仔细看看,发现 CustomizeRedisCache 就是需要改造的。

      public void evict(RedisCacheElement element)
      public void evict(Object key) 
    

    这2个函数。很可以,2个文件粘贴出来,直接做成注入,发现就直接可以在 @Cacheable 的时候断点看了。
    这2个就是在删除缓存时候使用的。


    改造一波

    代码进行了删减,需要修改后的,可以联系我

    CustomizedRedisCacheManager

    
    /**
     * 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

    
    /**
     * 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<? extends Object, ? extends Object> 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> T get(Object key, Class<T> 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

  • 相关阅读:
    XMLHttpRequest 对象 的属性与方法
    永远的福气 陈慧琳
    win32.Jadtre.B不用删除文件解决办法(网页嵌入一段恶意js )
    整理一些PHP函数,这些函数用的不是非常多,但是又非常重要,如果适当的用起来,有可以提升性能
    循环file_get_contents()部分内容不能获取的问题
    php下载图片到用户客户端
    php中break,continue,exit的使用与区别
    解决android setText不能int的问题
    用htaccess限制ip访问的方法
    查看表结构的命令show columns from 表名
  • 原文地址:https://www.cnblogs.com/ykkBlog/p/14503930.html
Copyright © 2011-2022 走看看