2019独角兽企业重金招聘Python工程师标准>>>

前言

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

一点知识

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文件依赖

      <!-- redis cache --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- ehcache缓存 --><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId></dependency>

1.创建配置类。

CacheConfig.java

/**
*
* @ClassName   类名:CacheConfig
* @Description 功能说明:缓存配置类
* <p>
* TODO
*</p>
************************************************************************
* @date        创建日期:2019年3月7日
* @author      创建人:oKong
* @version     版本号:V1.0
*<p>
***************************修订记录*************************************
*
*   2019年3月7日   oKong   创建该类功能。
*
***********************************************************************
*</p>
*/
@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*/@Beanpublic 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)@Primarypublic 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 功能说明:
* <p>
* TODO
*</p>
************************************************************************
* @date        创建日期:2019年3月7日
* @author      创建人:oKong
* @version     版本号:V1.0
*<p>
***************************修订记录*************************************
*
*   2019年3月7日   oKong   创建该类功能。
*
***********************************************************************
*</p>
*/
@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

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="ehcache.xsd"><!--timeToIdleSeconds 当缓存闲置n秒后销毁 --><!--timeToLiveSeconds 当缓存存活n秒后销毁 --><!-- 缓存配置 name:缓存名称。 maxElementsInMemory:缓存最大个数。 eternal:对象是否永久有效,一但设置了,timeout将不起作用。 timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。 timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。 diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 maxElementsOnDisk:硬盘最大缓存个数。 diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。  memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是
LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。 clearOnFlush:内存数量最大时是否清除。 --><!-- 磁盘缓存位置 --><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,即对应cacheName的值 --><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中已经存在相关记录了

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

参考资料

  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/

转载于:https://my.oschina.net/xiedeshou/blog/3019562

SpringBoot | 第三十六章:集成多CacheManager相关推荐

  1. 【正点原子FPGA连载】第三十六章 基于OV5640的PL以太网视频传输实验-摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  2. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十六章 UCOSII 实验 1任务调度...

    1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十六章 ...

  3. 第三百三十六章 斗宗强者间的大战!

    第三百三十六章 斗宗强者间的大战! <script language="javascript" src="/js/style2.js"></s ...

  4. 第一卷 第一百三十六章 好白菜

    第一卷 第一百三十六章 好白菜 其实我最恨两种人,一种是始乱终弃的小白脸,一种就是生孩子不养活的臭娘们儿.**  提供本书txt电子书下载 **既然你能生就要能养啊,虽然我不知道井里的那个死孩子的母亲 ...

  5. 第三十六章 SQL函数 CURRENT_TIME

    文章目录 第三十六章 SQL函数 CURRENT_TIME 大纲 参数 描述 小数秒精度 示例 第三十六章 SQL函数 CURRENT_TIME 返回当前本地时间的日期/时间函数. 大纲 CURREN ...

  6. 《快速掌握PyQt5》第三十六章 用PyQtGraph绘制可视化数据图表

    第三十六章 用PyQtGraph绘制可视化数据图表 36.1 下载PyQtGraph 36.2 基础知识与用法 36.3 将PyQtGraph嵌入到PyQt5中 36.4 小结 <快速掌握PyQ ...

  7. 第三十六章:路由:相关主题

    用户空间配置工具: 路由的配置可以使用net-tools软件包(route命令)和IPROUTE2(ip rouute 和ip rule)软件包.net-tools不能配置任何高级路由功能,如多路径和 ...

  8. 奋斗吧,程序员——第三十六章 落花人独立,微雨燕双飞

    什么什么,要我别倒下? 废话,不看着情敌们在我面前一个个倒下,然后踩着他们的尸体过去继续战斗,我怎么可能比他们先一刻倒下. 生命的意义在于不屈的抗争,只要情敌一天未清除,我们就不能退出战斗. 我们必须 ...

  9. SpringBoot | 第三十五章:Mybatis的集成和使用

    2019独角兽企业重金招聘Python工程师标准>>> 前言 最近收到公众号留言说,单纯的Mybatis的集成和使用.前面在第九章:Mybatis-plus的集成和使用介绍了基于my ...

最新文章

  1. 万字大白话带你重拾计算机网络
  2. Visual Studio 2010 Ultimate测试体系结构
  3. linux 磁盘性能监控
  4. jenkins+ant+git+android搭建笔记
  5. ​一网打尽 Linux 必备技能,就靠它了!
  6. 海思108M 4D1模式含义
  7. C语言文件操作 fopen, fclose, mkdir(打开关闭文件,建文件夹,判断文件是否存在可读或可写)
  8. LeetCode 162. 寻找峰值(二分查找)
  9. 同样是Java程序员,如何比别人更优秀?
  10. springMVC小记
  11. tomcat java_opts 最大_tomcat性能优化(JAVA_OPTS)
  12. 软件开发:到底谁还在传言软件巨头濒临死亡?
  13. 计算机二级python考试大纲2020_【2020年9月全国计算机二级Python考试大纲】- 环球网校...
  14. java枚举ordinal()接口怎么用,java.lang.Enum.ordinal()方法实例
  15. HDU 4699 Editor(双向链表)
  16. JavaScript 严格模式(strict mode)
  17. springmvc GET POST 接受参数方式
  18. 删除的微信好友可以恢复吗?不小心把微信好友删了怎么找回
  19. python第三方库汇总
  20. 利用CSS3实现蓝天白云大海景象

热门文章

  1. CIO:辩证看待云计算 游戏规则已改变
  2. 提高页面载入速度简单易行的四个办法。
  3. 整合资源_java的基础关键字
  4. BE镜像还原系统过程
  5. 海翰聚焦:专家一天话,价值八千八?
  6. ES6中的class是如何实现的?(附Babel编译的ES5代码详解)
  7. Python中读取、显示和保存图片的方法
  8. java B2B2C 源码 多级分销Springcloud多租户电子商城系统(十)用spring Restdocs创建API文档...
  9. 使用fork并发处理多个client的请求和对等通信p2p
  10. nagios插件--磁盘IO监控