前言
今天有网友咨询了一个问题:如何在一个工程中使用多种缓存进行差异化缓存,即实现多个
cacheManager
灵活切换。原来没有遇见这种场景,今天下班抽空试了下,以下就把如何实现的简单记录下。
一点知识
在
SpringBoot
中使用Spring Cache
可以轻松实现缓存,是Spring
框架提供的对缓存使用的抽象类,支持多种缓存,比如Redis
、EHCache
等,集成很方便。同时提供了多种注解来简化缓存的使用,可对方法进行缓存。具体如何集成,之前的文章已经有详细介绍了,感兴趣的同学可点击: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
已经为我们自动配置了EhCache
、Collection
、Guava
、ConcurrentMap
等缓存,默认使用ConcurrentMapCacheManager
。SpringBoot
的application.properties
配置文件,使用spring.cache
前缀的属性进行配置。
application配置
1 | spring.cache.type=#缓存的技术类型 |
这里为了演示多cacheManager
实现,这里使用redis
和ehcache
进行集成。
集成Redis和ehcache
0.pom文件依赖1
2
3
4
5
6
7
8
9
10 <!-- 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
1 | /** |
注:其实就是配置多个cacheManager
。但这里需要注意,要设置一个默认的cacheManager
,即注解在未设置cacheManager
时,自动使用此缓存管理类进行缓存,同时,因为注入了多个cacheManaager
,需要在默认的管理器方法上加上@Primary
注解。不然,会出现一下异常:1
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
即可。1
@Primary 优先考虑,优先考虑被注解的对象注入
2.编写测试类,默认是使用redis缓存
,若想指定缓存,只需要设置cacheManager
的值即可。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/**
*
* @ClassName 类名:DemoController
* @Description 功能说明:
* <p>
* TODO
*</p>
************************************************************************
* @date 创建日期:2019年3月7日
* @author 创建人:oKong
* @version 版本号:V1.0
*<p>
***************************修订记录*************************************
*
* 2019年3月7日 oKong 创建该类功能。
*
***********************************************************************
*</p>
*/
4j
public class DemoController {
"/redis/{key}") (
"redis",key="#key",cacheManager=CacheConfig.CacheManagerName.REDIS_CACHE_MANAGER) (value =
public String cacheRedisTest(@PathVariable("key") String key) {
log.info("redis,key={}", key);
return key;
}
"/ehcache/{key}") (
"oKongCache",key="#key",cacheManager=CacheConfig.CacheManagerName.EHCACHE_CACHE_MAANGER) (value =
public String cacheEhcacheTest(@PathVariable("key") String key) {
log.info("ehcache,key={}", key);
return key;
}
"/default/{key}") (
"default",key="#key") (value =
public String cacheDefaultTest(@PathVariable("key") String key) {
log.info("default,key={}", key);
return key;
}
}
3.配置application文件,加入相关配置。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 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
。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<?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.启动应用。
依次访问:
- http://127.0.0.1:8080/redis/okong
- http://127.0.0.1:8080/ehcache/okong
- http://127.0.0.1:8080/default/okong
可以看看redis中已经存在相关记录了
之后多访问几次,查看控制台,是没有输出的。
参考资料
总结
本章节主要介绍了多
cacheManager
的灵活切换,以便实现更加灵活的缓存使用,可以根据具体的业务需求,进行差异化操作。关于ehcache
的使用,现在用的不多了,所以相关配置参数,可以自行搜索下了。
最后
目前互联网上很多大佬都有
SpringBoot
系列教程,如有雷同,请多多包涵了。原创不易,码字不易,还希望大家多多支持。若文中有所错误之处,还望提出,谢谢。
老生常谈
- 个人QQ:
499452441
- 微信公众号:
lqdevOps
个人博客:http://blog.lqdev.cn
完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-36
原文地址:http://blog.lqdev.cn/2018/12/03/springboot/chapter-thirty-six/