SpringBoot | 第三十六章:集成多CacheManager

前言

今天有网友咨询了一个问题:如何在一个工程中使用多种缓存进行差异化缓存,即实现多个cacheManager灵活切换。原来没有遇见这种场景,今天下班抽空试了下,以下就把如何实现的简单记录下。

  • 一点知识
    • 关于CacheMananger
  • 集成Redis和ehcache
  • 参考资料
  • 总结
  • 最后
  • 老生常谈

一点知识

SpringBoot中使用Spring Cache可以轻松实现缓存,是Spring框架提供的对缓存使用的抽象类,支持多种缓存,比如RedisEHCache等,集成很方便。同时提供了多种注解来简化缓存的使用,可对方法进行缓存。具体如何集成,之前的文章已经有详细介绍了,感兴趣的同学可点击:SpringBoot | 第十一章:Redis的集成和简单使用。这里就不再阐述了,一下简单较少下cacheManager

关于CacheMananger

针对不同的缓存技术,需要实现不同的cacheManager,Spring定义了如下的cacheManger实现。

CacheManger 描述
SimpleCacheManager 使用简单的Collection来存储缓存,主要用于测试
ConcurrentMapCacheManager 使用ConcurrentMap作为缓存技术(默认)
NoOpCacheManager 测试用
EhCacheCacheManager 使用EhCache作为缓存技术,以前在hibernate的时候经常用
GuavaCacheManager 使用google guava的GuavaCache作为缓存技术
HazelcastCacheManager 使用Hazelcast作为缓存技术
JCacheCacheManager 使用JCache标准的实现作为缓存技术,如Apache Commons JCS
RedisCacheManager 使用Redis作为缓存技术

常规的SpringBoot已经为我们自动配置了EhCacheCollectionGuavaConcurrentMap等缓存,默认使用ConcurrentMapCacheManagerSpringBootapplication.properties配置文件,使用spring.cache前缀的属性进行配置。

application配置

spring.cache.type=#缓存的技术类型
spring.cache.cache-names=应用程序启动创建缓存的名称
spring.cache.ehcache.config=ehcache的配置文件位置
spring.cache.infinispan.config=infinispan的配置文件位置
spring.cache.jcache.config=jcache配置文件位置
spring.cache.jcache.provider=当多个jcache实现类时,指定选择jcache的实现类

这里为了演示多cacheManager实现,这里使用redisehcache进行集成。

集成Redis和ehcache

0.pom文件依赖

	    
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-data-redisartifactId>
		dependency>
		
		<dependency>
			<groupId>net.sf.ehcachegroupId>
			<artifactId>ehcacheartifactId>
		dependency>

1.创建配置类。

CacheConfig.java

/** 
*
* @ClassName   类名:CacheConfig 
* @Description 功能说明:缓存配置类
* 

* TODO *

************************************************************************ * @date 创建日期:2019年3月7日 * @author 创建人:oKong * @version 版本号:V1.0 *

***************************修订记录************************************* * * 2019年3月7日 oKong 创建该类功能。 * *********************************************************************** *

*/
@Configuration @EnableCaching public class CacheConfig { /** * cacheManager名称 */ public interface CacheManagerName { /** * redis */ String REDIS_CACHE_MANAGER = "redisCacheManager"; /** * ehCache */ String EHCACHE_CACHE_MAANGER = "ehCacheCacheManager"; } /** * 定义 StringRedisTemplate ,指定序列号和反序列化的处理类 * @param factory * @return */ @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); Jackson2JsonRedisSerializer<Object> 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); //序列化 值时使用此序列化方法 template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } @Bean(CacheConfig.CacheManagerName.REDIS_CACHE_MANAGER) @Primary public RedisCacheManager redisCacheManager(RedisTemplate<String,String> redisTemplate) { RedisCacheManager rcm = new RedisCacheManager(redisTemplate); //使用前缀 rcm.setUsePrefix(true); //缓存分割符 默认为 ":" // rcm.setCachePrefix(new DefaultRedisCachePrefix(":")); //设置缓存过期时间 //rcm.setDefaultExpiration(60);//秒 return rcm; } @Bean(CacheConfig.CacheManagerName.EHCACHE_CACHE_MAANGER) public EhCacheCacheManager EhcacheManager() { EhCacheCacheManager ehCacheManager = new EhCacheCacheManager(); return ehCacheManager; } }

注:其实就是配置多个cacheManager。但这里需要注意,要设置一个默认的cacheManager,即注解在未设置cacheManager时,自动使用此缓存管理类进行缓存,同时,因为注入了多个cacheManaager,需要在默认的管理器方法上加上@Primary注解。不然,会出现一下异常:

No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary (or give it the name 'cacheManager') or declare a specific CacheManager to use, that serves as the default one.

至于原因。可以查看以下代码:

异常点

其实就是配置了多个bean,抛出了一个NoUniqueBeanDefinitionException异常。其实就是未指定一个默认的cacheManager,所以加上@Primary即可。

@Primary 优先考虑,优先考虑被注解的对象注入

2.编写测试类,默认是使用redis缓存,若想指定缓存,只需要设置cacheManager的值即可。

/** 
*
* @ClassName   类名:DemoController 
* @Description 功能说明:
* 

* TODO *

************************************************************************ * @date 创建日期:2019年3月7日 * @author 创建人:oKong * @version 版本号:V1.0 *

***************************修订记录************************************* * * 2019年3月7日 oKong 创建该类功能。 * *********************************************************************** *

*/
@RestController @Slf4j public class DemoController { @RequestMapping("/redis/{key}") @Cacheable(value = "redis",key="#key",cacheManager=CacheConfig.CacheManagerName.REDIS_CACHE_MANAGER) public String cacheRedisTest(@PathVariable("key") String key) { log.info("redis,key={}", key); return key; } @RequestMapping("/ehcache/{key}") @Cacheable(value = "oKongCache",key="#key",cacheManager=CacheConfig.CacheManagerName.EHCACHE_CACHE_MAANGER) public String cacheEhcacheTest(@PathVariable("key") String key) { log.info("ehcache,key={}", key); return key; } @RequestMapping("/default/{key}") @Cacheable(value = "default",key="#key") public String cacheDefaultTest(@PathVariable("key") String key) { log.info("default,key={}", key); return key; } }

3.配置application文件,加入相关配置。

# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0

# ehcache配置地址
spring.cache.ehcache.config=ehcache.xml

配置ehcache.xml文件,设置cacheName


<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd">
    
    
    
    
    <diskStore path="java.io.tmpdir" />
    
    <defaultCache 
        maxElementsInMemory="10000" 
        eternal="false"
        timeToIdleSeconds="120" 
        timeToLiveSeconds="120" 
        maxElementsOnDisk="10000000"
        diskExpiryThreadIntervalSeconds="120" 
        memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap" />
    defaultCache>

    
    <cache name="oKongCache" 
        eternal="false" 
        timeToIdleSeconds="2400"
        timeToLiveSeconds="2400" 
        maxEntriesLocalHeap="10000"
        maxEntriesLocalDisk="10000000" 
        diskExpiryThreadIntervalSeconds="120"
        overflowToDisk="false" 
        memoryStoreEvictionPolicy="LRU">
    cache>
ehcache>

关于其属性参数,大家可自行百度下,使用的不多呀,(┬_┬)

4.启动应用。
依次访问:

  1. http://127.0.0.1:8080/redis/okong
  2. http://127.0.0.1:8080/ehcache/okong
  3. http://127.0.0.1:8080/default/okong

可以看看redis中已经存在相关记录了

redis

之后多访问几次,查看控制台,是没有输出的。

console

参考资料

  1. https://docs.spring.io/spring-boot/docs/1.5.15.RELEASE/reference/htmlsingle/#boot-features-caching-provider

总结

本章节主要介绍了多cacheManager的灵活切换,以便实现更加灵活的缓存使用,可以根据具体的业务需求,进行差异化操作。关于ehcache的使用,现在用的不多了,所以相关配置参数,可以自行搜索下了。

最后

目前互联网上很多大佬都有SpringBoot系列教程,如有雷同,请多多包涵了。原创不易,码字不易,还希望大家多多支持。若文中有所错误之处,还望提出,谢谢。

老生常谈

  • 个人QQ:499452441
  • 微信公众号:lqdevOps

公众号

个人博客:http://blog.lqdev.cn

完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-36

原文地址:https://blog.lqdev.cn/2019/03/08/springboot/chapter-thirty-six/

你可能感兴趣的:(SpringBoot)