【小家Spring】Spring Boot中使用RedisTemplate优雅的操作Redis,并且解决RedisTemplate泛型注入失败的问题(下)

简介: 【小家Spring】Spring Boot中使用RedisTemplate优雅的操作Redis,并且解决RedisTemplate泛型注入失败的问题(下)

设置默认的缓存管理器(CacheManager)


缓存管理器,为Spring抽象出来管理缓存的。若我们没有手动注册过CacheManager这个Bean,那么Boot容器会自动给我们注册一个。


@Bean
  public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory,
      ResourceLoader resourceLoader) {}
//注意:它执行的条件都为@ConditionalOnMissingBean(CacheManager.class),都必须为在容器中没有发现Bean,才会自动自动注册哟


然后,当我们一个项目中使用了多种缓存的时候(比如Redis、Ehcache、Caffeine等),并且自己注册了多个CacheManager的时候,并且我们开启了缓存注解@EnableCaching,我们就需要配置默认的缓存管理器了,否则就会启动失败~~

Spring内置了一些常用的缓存管理器的支持:

image.png


这个时候如果我们在上面Redis的基础上,再导入EhCache:


        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.5</version>
        </dependency>


小Tips:Spring现在默认支持的ehcache版本为2.x版,3.x版本不支持。若要使用3.x版本进行集成,请参考相关博文。spring-boot-starter-cache此组件能提供支持


这个时候我们配置类如下:

@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public EhCacheCacheManager ehCacheManager() {
        EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager();
        return ehCacheCacheManager;
    }
    //备注:这是boot2.x的配置。1.x的配置可以直接new即可  会少很多代码
    //RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory factory,
                                          ResourceLoader resourceLoader) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();  // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
        config = config.entryTtl(Duration.ofMinutes(1))     // 设置缓存的默认过期时间,也是使用Duration设置
                .disableCachingNullValues();     // 不缓存空值
        // 设置一个初始化的缓存空间set集合
        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("my-redis-cache1");
        cacheNames.add("my-redis-cache2");
        // 对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("my-redis-cache1", config);
        configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)     // 使用自定义的缓存配置初始化一个cacheManager
                .initialCacheNames(cacheNames)  // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
                .withInitialCacheConfigurations(configMap)
                .build();
        return cacheManager;
    }
}


报错:


java.lang.IllegalStateException: No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary or declare a specific CacheManager to use.
  at org.springframework.cache.interceptor.CacheAspectSupport.afterSingletonsInstantiated(CacheAspectSupport.java:223) ~[spring-context-5.1.2.RELEASE.jar:5.1.2.RELEASE]
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:863) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]


源码看原因,其实很简单。就是要为缓存注解分配一个默认的缓存管理器,如果你给定两个,我肯定就报错了嘛


@Override
  public void afterSingletonsInstantiated() {
    if (getCacheResolver() == null) {
      // Lazily initialize cache resolver via default cache manager...
      Assert.state(this.beanFactory != null, "CacheResolver or BeanFactory must be set on cache aspect");
      try {
        setCacheManager(this.beanFactory.getBean(CacheManager.class));
      }
      catch (NoUniqueBeanDefinitionException ex) {}



解决方案:在你希望的默认缓存管理器上加是上@Primary注解即可(一般都标注在RedisCacheManager上面)


这样,我们就实现了同时使用多个缓存的情况,可以和谐共处了。


设置缓存的过期时间(通过缓存管理器统一设置)


这个需求经常遇到,最灵活的肯定是使用RedisTemplate的expire方法进行设置。而本处再介绍一个全局方法(也适用于缓存注解),来管理一些频繁使用的key的过期时间。


CacheManager功能其实很简单就是管理cache,接口只有两个方法,根据容器名称获取一个Cache。还有就是返回所有的缓存名称。

//根据名称获取一个Cache(在实现类里面是如果有这个Cache就返回,没有就新建一个Cache放到Map容器中)
Cache getCache(String name);
// 返回所有的缓存名称
Collection<String> getCacheNames();


关于自定义拦截,让缓存注解也支持过期时间的书写,可以提供思路:打断点跟踪拦截器:org.springframework.cache.interceptor.CacheInterceptor来分析


为了方便,本文以Boot1.x为例:


        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        //设置默认的过期时间(不设置缓存不过期) 单位:秒
        cacheManager.setDefaultExpiration(3600L);
      //针对具体的key  设置过期时间   所以我们完全可以定制化
      //备注:此过期时间没更新一次,都会跟新成最新的值的过期时间的
      Map<String, Long> expires = new HashMap<String, Long>();
         expires.put("news", 60L);
        redisCacheManager.setExpires(expires);
      //是否启用前缀 默认为false
        cacheManager.setUsePrefix(true);


下一篇博文,我会重点分析RedisTemplate的六大序列化方式,以及使用时候我们常见的坑(有的是巨坑)

【小家Spring】RedisTemplate的序列化方式大解读,含FastJsonRedisSerializer、Genericjackson2jsonredisserializer序列化的坑

相关文章
|
6月前
|
NoSQL Java 网络安全
SpringBoot启动时连接Redis报错:ERR This instance has cluster support disabled - 如何解决?
通过以上步骤一般可以解决由于配置不匹配造成的连接错误。在调试问题时,一定要确保服务端和客户端的Redis配置保持同步一致。这能够确保SpringBoot应用顺利连接到正确配置的Redis服务,无论是单机模式还是集群模式。
582 5
|
6月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
6月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
6月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
684 2
|
7月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
6386 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
存储 JSON Java
832 0
|
7月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
647 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
7月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
2520 0
|
9月前
|
NoSQL Java Redis
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
740 2