国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - @CacheEvict + redis實現批量刪除緩存

@CacheEvict + redis實現批量刪除緩存

2022-02-16 14:59llllllllll4er5ty Java教程

這篇文章主要介紹了@CacheEvict + redis實現批量刪除緩存方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

@CacheEvict + redis批量刪除緩存

一、@Cacheable注解

添加緩存。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 * @Cacheable
 * 將方法的運行結果進行緩存;以后再要相同的數據,直接從緩存中獲取,不用調用方法;
 * CacheManager管理多個Cache組件,對緩存的真正CRUD操作在Cache組件中,每一個緩存組件有自己唯一一個名字;
 *
 *
 * 原理:
 *   1、自動配置類;CacheAutoConfiguration
 *   2、緩存的配置類
 *   org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration
 *   org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默認】
 *   org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
 *   3、哪個配置類默認生效:SimpleCacheConfiguration;
 *
 *   4、給容器中注冊了一個CacheManager:ConcurrentMapCacheManager
 *   5、可以獲取和創建ConcurrentMapCache類型的緩存組件;他的作用將數據保存在ConcurrentMap中;
 *
 *   運行流程:
 *   @Cacheable:
 *   1、方法運行之前,先去查詢Cache(緩存組件),按照cacheNames指定的名字獲取;
 *      (CacheManager先獲取相應的緩存),第一次獲取緩存如果沒有Cache組件會自動創建。
 *   2、去Cache中查找緩存的內容,使用一個key,默認就是方法的參數;
 *      key是按照某種策略生成的;默認是使用keyGenerator生成的,默認使用SimpleKeyGenerator生成key;
 *          SimpleKeyGenerator生成key的默認策略;
 *                  如果沒有參數;key=new SimpleKey();
 *                  如果有一個參數:key=參數的值
 *                  如果有多個參數:key=new SimpleKey(params);
 *   3、沒有查到緩存就調用目標方法;
 *   4、將目標方法返回的結果,放進緩存中
 *
 *   @Cacheable標注的方法執行之前先來檢查緩存中有沒有這個數據,默認按照參數的值作為key去查詢緩存,
 *   如果沒有就運行方法并將結果放入緩存;以后再來調用就可以直接使用緩存中的數據;
 *
 *   核心:
 *      1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】組件
 *      2)、key使用keyGenerator生成的,默認是SimpleKeyGenerator
 *
 *
 *   幾個屬性:
 *      cacheNames/value:指定緩存組件的名字;將方法的返回結果放在哪個緩存中,是數組的方式,可以指定多個緩存;
 *
 *      key:緩存數據使用的key;可以用它來指定。默認是使用方法參數的值  1-方法的返回值
 *              編寫SpEL; #i d;參數id的值   #a0  #p0  #root.args[0]
 *              getEmp[2]
 *
 *      keyGenerator:key的生成器;可以自己指定key的生成器的組件id
 *              key/keyGenerator:二選一使用;
 *
 *
 *      cacheManager:指定緩存管理器;或者cacheResolver指定獲取解析器
 *
 *      condition:指定符合條件的情況下才緩存;
 *              ,condition = "#id>0"
 *          condition = "#a0>1":第一個參數的值》1的時候才進行緩存
 *
 *      unless:否定緩存;當unless指定的條件為true,方法的返回值就不會被緩存;可以獲取到結果進行判斷
 *              unless = "#result == null"
 *              unless = "#a0==2":如果第一個參數的值是2,結果不緩存;
 *      sync:是否使用異步模式
 *
 */

二、@CacheEvict注解

清除緩存。

cacheNames/value: 指定緩存組件的名字;將方法的返回結果放在哪個緩存中,是數組的方式,可以指定多個緩存;
key 緩存數據使用的key
allEntries 是否清除這個緩存中所有的數據。true:是;false:不是
beforeInvocation 緩存的清除是否在方法之前執行,默認代表緩存清除操作是在方法執行之后執行;如果出現異常緩存就不會清除。true:是;false:不是

三、批量刪除緩存

現實應用中,某些緩存都有相同的前綴或者后綴,數據庫更新時,需要刪除某一類型(也就是相同前綴)的緩存。

而@CacheEvict只能單個刪除key,不支持模糊匹配刪除。

解決辦法:使用redis + @CacheEvict解決。

@CacheEvict實際上是調用RedisCache的evict方法刪除緩存的。下面為RedisCache的部分代碼,可以看到,evict方法是不支持模糊匹配的,而clear方法是支持模糊匹配的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * (non-Javadoc)
 * @see org.springframework.cache.Cache#evict(java.lang.Object)
 */
@Override
public void evict(Object key) {
    cacheWriter.remove(name, createAndConvertCacheKey(key));
}
 
/*
 * (non-Javadoc)
 * @see org.springframework.cache.Cache#clear()
 */
@Override
public void clear() {
 
    byte[] pattern = conversionService.convert(createCacheKey("*"), byte[].class);
    cacheWriter.clean(name, pattern);
}

所以,只需重寫RedisCache的evict方法就可以解決模糊匹配刪除的問題。

四、代碼

4.1 自定義RedisCache:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class CustomizedRedisCache extends RedisCache {
    private static final String WILD_CARD = "*";
    private final String name;
    private final RedisCacheWriter cacheWriter;
    private final ConversionService conversionService;
    protected CustomizedRedisCache(String name, RedisCacheWriter cacheWriter, RedisCacheConfiguration cacheConfig) {
        super(name, cacheWriter, cacheConfig);
        this.name = name;
        this.cacheWriter = cacheWriter;
        this.conversionService = cacheConfig.getConversionService();
    }
 
    @Override
    public void evict(Object key) {
        if (key instanceof String) {
            String keyString = key.toString();
            if (keyString.endsWith(WILD_CARD)) {
                evictLikeSuffix(keyString);
                return;
            }
            if (keyString.startsWith(WILD_CARD)) {
                evictLikePrefix(keyString);
                return;
            }
        }
        super.evict(key);
    }
 
    /**
     * 前綴匹配
     *
     * @param key
     */
    public void evictLikePrefix(String key) {
        byte[] pattern = this.conversionService.convert(this.createCacheKey(key), byte[].class);
        this.cacheWriter.clean(this.name, pattern);
    }
 
    /**
     * 后綴匹配
     *
     * @param key
     */
    public void evictLikeSuffix(String key) {
        byte[] pattern = this.conversionService.convert(this.createCacheKey(key), byte[].class);
        this.cacheWriter.clean(this.name, pattern);
    
}

4.2 重寫RedisCacheManager,使用自定義的RedisCache:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class CustomizedRedisCacheManager extends RedisCacheManager {
    private final RedisCacheWriter cacheWriter;
    private final RedisCacheConfiguration defaultCacheConfig;
    private final Map<String, RedisCacheConfiguration> initialCaches = new LinkedHashMap<>();
    private boolean enableTransactions;
 
    public CustomizedRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
        this.cacheWriter = cacheWriter;
        this.defaultCacheConfig = defaultCacheConfiguration;
    }
 
    public CustomizedRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration, String... initialCacheNames) {
        super(cacheWriter, defaultCacheConfiguration, initialCacheNames);
        this.cacheWriter = cacheWriter;
        this.defaultCacheConfig = defaultCacheConfiguration;
    }
 
    public CustomizedRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration, boolean allowInFlightCacheCreation, String... initialCacheNames) {
        super(cacheWriter, defaultCacheConfiguration, allowInFlightCacheCreation, initialCacheNames);
        this.cacheWriter = cacheWriter;
        this.defaultCacheConfig = defaultCacheConfiguration;
    }
 
    public CustomizedRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration, Map<String, RedisCacheConfiguration> initialCacheConfigurations) {
        super(cacheWriter, defaultCacheConfiguration, initialCacheConfigurations);
        this.cacheWriter = cacheWriter;
        this.defaultCacheConfig = defaultCacheConfiguration;
    }
 
    public CustomizedRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration, Map<String, RedisCacheConfiguration> initialCacheConfigurations, boolean allowInFlightCacheCreation) {
        super(cacheWriter, defaultCacheConfiguration, initialCacheConfigurations, allowInFlightCacheCreation);
        this.cacheWriter = cacheWriter;
        this.defaultCacheConfig = defaultCacheConfiguration;
    }
 
    /**
     * 這個構造方法最重要
     **/
    public CustomizedRedisCacheManager(RedisConnectionFactory redisConnectionFactory, RedisCacheConfiguration cacheConfiguration) {
        this(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),cacheConfiguration);
    }
 
    /**
     * 覆蓋父類創建RedisCache
     */
    @Override
    protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) {
        return new CustomizedRedisCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfig);
    }
 
    @Override
    public Map<String, RedisCacheConfiguration> getCacheConfigurations() {
        Map<String, RedisCacheConfiguration> configurationMap = new HashMap<>(getCacheNames().size());
        getCacheNames().forEach(it -> {
            RedisCache cache = CustomizedRedisCache.class.cast(lookupCache(it));
            configurationMap.put(it, cache != null ? cache.getCacheConfiguration() : null);
        });
        return Collections.unmodifiableMap(configurationMap);
    }
}

4.3 在RedisTemplateConfig中使用自定義的CacheManager

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Bean
 public CacheManager oneDayCacheManager(RedisConnectionFactory factory) {
  RedisSerializer<String> redisSerializer = new StringRedisSerializer();
  Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
 
  //解決查詢緩存轉換異常的問題
  ObjectMapper om = new ObjectMapper();
  om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  jackson2JsonRedisSerializer.setObjectMapper(om);
 
  // 配置序列化(解決亂碼的問題)
  RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
    // 1天緩存過期
    .entryTtl(Duration.ofDays(1))
    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
    .computePrefixWith(name -> name + ":")
    .disableCachingNullValues();
  return new CustomizedRedisCacheManager(factory, config);
 }

4.4 在代碼方法上使用@CacheEvict模糊匹配刪除

?
1
2
3
4
5
6
7
8
9
@Cacheable(value = "current_group", cacheManager = "oneDayCacheManager",
            key = "#currentAttendanceGroup.getId() + ':' + args[1]", unless = "#result eq null")
    public String getCacheAttendanceId(CurrentAttendanceGroupDO currentAttendanceGroup, String dateStr) {
        // 方法體
    }
 
    @CacheEvict(value = "current_group", key = "#currentAttendanceGroup.getId() + ':' + '*'", beforeInvocation = true)
    public void deleteCacheAttendanceId(CurrentAttendanceGroupDO currentAttendanceGroup) {
    }

注意:如果RedisTemplateConfig中有多個CacheManager,可以使用@Primary注解標注默認生效的CacheManager

@CacheEvict清除指定下所有緩存

?
1
@CacheEvict(cacheNames = "parts:grid",allEntries = true)

此注解會清除part:grid下所有緩存

@CacheEvict要求指定一個或多個緩存,使之都受影響。

此外,還提供了一個額外的參數allEntries 。表示是否需要清除緩存中的所有元素。

默認為false,表示不需要。當指定了allEntries為true時,Spring Cache將忽略指定的key。

有的時候我們需要Cache一下清除所有的元素。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/llllllllll4er5ty/article/details/106337559

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 精品久久久久久久 | 在线观看亚洲a | 国产精品成av人在线视午夜片 | a在线观看免费视频 | 久久久久国产精品免费免费搜索 | 色.com| 日韩在线免费 | 欧美婷婷 | 日本中文字幕在线播放 | 精品国产一区探花在线观看 | 亚洲精品综合 | 免费日韩在线 | 污视频网站在线观看 | 在线播放亚洲 | 思热99re视热频这里只精品 | 欧美电影在线观看网站 | 一区二区精品视频 | 日韩三级黄色片 | 国产成年人视频 | 国产精品久久久久久久久久久久午夜片 | 久久久久久av | 欧美综合成人网 | 精品国产一区二区三区高潮视 | 一级做a爰片性色毛片精油 欧美中文字幕在线观看 | 国产精品亚洲综合 | 精一区二区 | 日韩成人一区二区 | 97久久香蕉国产线看观看 | 午夜爱爱毛片xxxx视频免费看 | 欧美精品一区二区三区蜜桃视频 | 成年黄色在线观看 | 欧美一区二区精品 | 日韩超碰| 精品视频免费观看 | 夜夜av | 国产精品不卡一区 | 一区二区在线看 | 日日操狠狠操 | 欧美日韩激情 | 欧美自拍小视频 | 午夜在线 |