• Spring Cache使用Redis自定义缓存key


    一、什么是Spring Cache

          从spring 3.1版本开始,提供了一种透明的方式来为现有的spring 应用添加cache。在应用层面与后端存储之间,提供了一层抽象,这层抽象目的在于封装各种可插拔的后端存储( ehcache guava redis),最小化因为缓存给现有业务代码带来的侵入。

        核心抽象主要体现在两个接口上
    org.springframework.cache.cache

    org.springframework.cache.cachemanager

    cache代表缓存本身,包含缓存的常用操作:增加、删除、读取等。

    CacheManager 是 Spring 各种缓存的抽象接口。抽象的意义在于屏蔽实现细节的差异和提供扩展性,这一层cache的抽象解耦了缓存的使用和缓存的后端存储,这样后续可以方便的更换后端存储。

    Spring 支持的常用 CacheManager 如下:

    CacheManager描述
    SimpleCacheManager使用简单的 Collection 来存储缓存
    ConcurrentMapCacheManager使用 java.util.ConcurrentHashMap 来实现缓存
    NoOpCacheManager仅测试用,不会实际存储缓存
    EhCacheCacheManger使用EhCache作为缓存技术。EhCache 是一个纯 Java 的进程内缓存框架,特点快速、精干,是 Hibernate 中默认的 CacheProvider,也是 Java 领域应用最为广泛的缓存
    JCacheCacheManager支持JCache(JSR-107)标准的实现作为缓存技术
    CaffeineCacheManager使用 Caffeine 作为缓存技术。用于取代 Guava 缓存技术。
    RedisCacheManager使用Redis作为缓存技术
    HazelcastCacheManager使用Hazelcast作为缓存技术
    CompositeCacheManager用于组合 CacheManager,可以从多个 CacheManager 中轮询得到相应的缓存

    二、核心注解

    Spring Cache 提供了 @Cacheable 、@CachePut 、@CacheEvict 、@Caching 等注解

    1、 @Cacheable

    缓存数据或者获取缓存数据

    属性值如下:

    属性/方法名解释
    value缓存名,必填,它指定了你的缓存存放在哪块命名空间
    cacheNames与 value 差不多,二选一即可
    key可选属性,可以使用 SpEL 标签自定义缓存的key
    keyGeneratorkey的生成器。key/keyGenerator二选一使用
    cacheManager指定缓存管理器
    cacheResolver指定获取解析器
    condition条件符合则缓存
    unless条件符合则不缓存
    sync是否使用异步模式,默认为false

    2、@CachePut

    修改缓存数据。

    属性/方法名解释
    value缓存名,必填,它指定了你的缓存存放在哪块命名空间
    cacheNames与 value 差不多,二选一即可
    key可选属性,可以使用 SpEL 标签自定义缓存的key
    keyGeneratorkey的生成器。key/keyGenerator二选一使用
    cacheManager指定缓存管理器
    cacheResolver指定获取解析器
    condition条件符合则缓存
    unless条件符合则不缓存

    3、@EnableCaching

    开启缓存功能,一般放在启动类上

    4、@CacheEvict

    清空缓存

    属性/方法名解释
    value缓存名,必填,它指定了你的缓存存放在哪块命名空间
    cacheNames与 value 差不多,二选一即可
    key可选属性,可以使用 SpEL 标签自定义缓存的key
    keyGeneratorkey的生成器。key/keyGenerator二选一使用
    cacheManager指定缓存管理器
    cacheResolver指定获取解析器
    condition条件符合则缓存
    allEntries是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存
    beforeInvocation是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存

    5、@Caching

    该注解可以实现同一个方法上同时使用多种注解。

    6、@CacheConfig

    统一配置@Cacheable中的value值

    三、接入Redis简单案例demo

    1、添加maven依赖

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-data-redis</artifactId>
    4. <version>${version}</version>
    5. </dependency>

    2、redis配置

    1. spring:
    2. redis:
    3. # Redis数据库索引(默认为0
    4. database: 0
    5. host: 127.0.0.1
    6. password: test
    7. # Redis服务器连接端口
    8. port: 6379
    9. # 连接超时时间(毫秒)
    10. timeout: 10000
    11. jedis:
    12. pool:
    13. # 连接池最大连接数(使用负值表示没有限制)
    14. max-active: 8
    15. # 连接池最大阻塞等待时间(使用负值表示没有限制)
    16. max-wait: -1
    17. # 连接池中的最大空闲连接
    18. max-idle: 8
    19. # 连接池中的最小空闲连接
    20. min-idle: 0

    3、配置CacheManager以及自定义key生成策略

    1. @EnableConfigurationProperties(CacheProperties.class)
    2. @Configuration(proxyBeanMethods = false)
    3. public class RedisCacheAutoConfiguration extends CachingConfigurerSupport {
    4. @Resource
    5. private RedisConnectionFactory factory;
    6. @Resource
    7. private CacheProperties cacheProperties;
    8. /**
    9. * 自定义生成redis-key
    10. */
    11. @Override
    12. @Primary
    13. @Bean
    14. public KeyGenerator keyGenerator() {
    15. return (target, method, params) -> {
    16. StringBuilder sb = new StringBuilder(cacheProperties.getCacheKeyPrefix()).append(":");
    17. sb.append(target.getClass().getName()).append(":");
    18. sb.append(method.getName()).append(":");
    19. for (Object param : params) {
    20. sb.append(param.toString()).append(":");
    21. }
    22. return sb.toString();
    23. };
    24. }
    25. @Override
    26. @Bean
    27. @Primary
    28. public CacheResolver cacheResolver() {
    29. return new SimpleCacheResolver(cacheManager());
    30. }
    31. /**
    32. * 配置CacheManager
    33. */
    34. @Primary
    35. @Bean
    36. @Override
    37. public CacheManager cacheManager() {
    38. RedisCacheConfiguration defaultRedisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
    39. //不缓存null结果
    40. // .disableCachingNullValues()
    41. .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer(CommonUtil.objectMapper())))
    42. //默认缓存30分钟
    43. .entryTtl(Duration.ofMinutes(30))
    44. //设置缓存key前缀
    45. .computePrefixWith(cacheKeyPrefix());
    46. return new CustomRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(factory), defaultRedisCacheConfiguration);
    47. }
    48. /**
    49. * key添加默认前缀方法
    50. */
    51. @Primary
    52. @Bean
    53. public CacheKeyPrefix cacheKeyPrefix() {
    54. return (String cacheName) -> {
    55. String[] arr = cacheName.split(CustomRedisCacheManager.SEPARATOR);
    56. StringBuilder sb = new StringBuilder(cacheProperties.getCacheKeyPrefix()).append(":").append(arr[0]).append(":");
    57. return sb.toString();
    58. };
    59. }
    60. }

    默认key前缀配置

    1. @Data
    2. @ConfigurationProperties(prefix = "test.cache")
    3. public class CacheProperties {
    4. /**
    5. * 缓存key前缀
    6. */
    7. private String cacheKeyPrefix;
    8. }

    自定义RedisCacheManager用于重写过期时间

    1. /**
    2. * 继承RedisCacheManager,重写createRedisCache方法,定义缓存过期时间
    3. */
    4. public class CustomRedisCacheManager extends RedisCacheManager {
    5. public static final String SEPARATOR = "#";
    6. public CustomRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
    7. super(cacheWriter, defaultCacheConfiguration);
    8. }
    9. @Override
    10. protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
    11. String[] arr = StringUtils.delimitedListToStringArray(name, SEPARATOR);
    12. name = arr[0];
    13. if (arr.length > 1) {
    14. // 缓存过期时间,注意单位是秒
    15. long ttl = Long.parseLong(arr[1]);
    16. cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
    17. }
    18. return super.createRedisCache(name, cacheConfig);
    19. }
    20. }

    使用案例

    1. //缓存失效时间1800s,key为拼接nick
    2. @Cacheable(value = "taoOrderAnalysis#1800", key = "#nick")
    3. public TaoOrderAnalysisDianzhang queryByNick(String nick) {
    4. TableRouter tableRouter = new TableRouter();
    5. tableRouter.setDbNo(1);
    6. tableRouter.setLogicTable("tao_order_analysis_dianzhang");
    7. return taoOrderAnalysisDianzhangMapper.queryByNick(nick, tableRouter);
    8. }

    在传递的nick为 -fengye- ,定义的cacheKeyPrefix为 test ,那么获取缓存使用key为:test:taoOrderAnalysis:-fengye-

  • 相关阅读:
    C#Winform新建工程
    Matlab图像处理基础(2):区域处理,边沿检测
    AXI VDMA回环测试
    如何使用Docker安装Kibana
    Spring学习(2) Spring的IOC底层实现
    大数据生态安全框架的实现原理与最佳实践(下篇)
    HDFS数据平衡
    超强 | 保险单据在线OCR,秒速识别保单信息
    微信小程序开发物流快递仓库平台+后台
    智能机房:全自动巡检+智能运维监控
  • 原文地址:https://blog.csdn.net/bird_tp/article/details/126727727