整合 不是分别整合几种缓存,而是同时使用多种缓存。根据项目中不同的缓存需求采用不同的缓存技术。
前些日子和朋友聊天时,他们项目中用到缓存,聊天中了解到,他们的缓存采用的是自己写的一个叫ICache的接口。缓存有redis缓存 和 OCS缓存(并不知道他们这个是什么鬼)。
看了他们接口API,基本和 spring的cache 框架一样。
其实他们也可以使用spring cache ,只需要编写一个OCSCache和 OCSCacheManager就行了。
一般项目中用缓存都是单一使用的,像朋友这样用好几种的不太多。其实spring cache 是支持多种缓存混合使用。
下面就是怎么利用spring cache 实现多种缓存技术的混合使用的。
spring 通过 cache 和 cacheManager 整合 和 管理不同缓存技术,通过 对应的CacheManager 管理 Cache,
比如 redis 、guava、ehcache、Jcache、还有自定义的cache。
org.springframework.cache.Cache
org.springframework.cache.CacheManager
Spring Cache 十分强大,在使用缓存时,对项目几乎没有侵入,使用时
只需要在需要使用的方法上面加上对应的注解,并且配合强大的SPEL,就可以很简单的使用各种缓存啦。以后切换缓存也是很方便。注解怎么使用可以参考其他的关于这方便的介绍。
@Cacheable 查询缓存
@CacheEvict 删除缓存条目
@CachePut 更新缓存条目
@Caching
@CacheConfig
@EnableCaching 启用Spring Cache
CacheManager简单描述就是用来存放Cache,Cache用于存放具体的key-value值。举个栗子:一个班级管理员 可以根据名字找到对应的学生,那么cacheManager 也是如此,CacheManager 负责缓存的创建和管理。常见的有下面集中。
RedisCacheManager 管理redis缓存
GuavaCacheManager 谷歌的guava缓存
EhchcheManager EhCache 管理
CompositeCacheManager 混合的缓存管理(可以同时使用多种缓存)
有时候在项目中会用到多种缓存同时使用的情况,就需要通过Spring提供的CompositeCacheManager来整合多种缓冲,通过缓存名字来指定使用的缓存。恕我语言匮乏,实在不知道该怎么说,只能贴代码了。有耐心的看下代码,就知道怎么做了。不懂的可以留言问我。
<!-- spring-cache --><!-- 谷歌的guava cache --> org.springframework.boot spring-boot-starter-cache <!-- redis --> com.google.guava guava 23.3-jre <!-- EhCache --> org.springframework.boot spring-boot-starter-data-redis net.sf.ehcache ehcache
application.properties:
# redis配置 spring.redis.host=localhost spring.redis.port=6379spring.redis.pool.max-idle=8spring.redis.pool.max-wait=-1spring.redis.pool.max-active=8# 指定ehcahce 配置文件路径 spring.cache.ehcache.config=cache/ehcache.xml spring.redis.database=0
ehcache.xml EhCachede配置文件,其实不想用XML.
<!-- diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。 参数解释如下: user.home – 用户主目录 user.dir – 用户当前工作目录 java.io.tmpdir – 默认临时文件路径 --> <!-- defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。 --> <!-- name:缓存名称。 maxElementsInMemory:缓存最大数目 maxElementsOnDisk:硬盘最大缓存个数。 eternal:对象是否永久有效,一但设置了,timeout将不起作用。 overflowToDisk:是否保存到磁盘,当系统当机时 timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使 用,可选属性,默认值是0,也就是可闲置时间无穷大。 timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅 当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。 diskPersistent:是否缓存虚拟机重启期数据Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该 有自己的一个缓冲区。 diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。 memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内 存。默认策略是LRU(最近最少使用)。 你可以设置为FIFO(先进先出)或是LFU(较少使用)。 clearOnFlush:内存数量最大时是否清除。 memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少 访问次数)。 FIFO,first in first out,这个是大家最熟的,先进先出。 LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面 所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地 方来缓存新的元素的时候, 那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。 -->
RedisConfig Redis配置 这个很简洁
package com.example.demo.config;import org.apache.log4j.Logger;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.StringRedisSerializer;import redis.clients.jedis.JedisPoolConfig;/**
*redis 配置
*/@Configurationpublic class RedisConfig extends CachingConfigurerSupport { private static Logger logger = Logger.getLogger(RedisConfig.class); @Bean
@ConfigurationProperties(prefix="spring.redis") public JedisPoolConfig getRedisConfig(){
JedisPoolConfig config = new JedisPoolConfig(); return config;
} @Bean
@ConfigurationProperties(prefix="spring.redis") public JedisConnectionFactory getConnectionFactory(){
JedisConnectionFactory factory = new JedisConnectionFactory();
JedisPoolConfig config = getRedisConfig();
factory.setPoolConfig(config);
logger.info("JedisConnectionFactory bean init success."); return factory;
} @Bean
public RedisTemplate, ?> getRedisTemplate(){
RedisTemplate,?> template = new StringRedisTemplate(getConnectionFactory());
template.setStringSerializer(new StringRedisSerializer());//设置redis 序列化
return template;
}
}
CacheConfig.java 这个缓存的配置
package com.example.demo.config;import com.example.demo.constant.CacheConstant;import com.google.common.cache.CacheBuilder;import com.google.common.collect.Lists;import net.sf.ehcache.config.CacheConfiguration;import net.sf.ehcache.store.MemoryStoreEvictionPolicy;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.EnableCaching;import org.springframework.cache.ehcache.EhCacheCacheManager;import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;import org.springframework.cache.guava.GuavaCacheManager;import org.springframework.cache.support.CompositeCacheManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.ClassPathResource;import org.springframework.data.redis.cache.DefaultRedisCachePrefix;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.core.RedisTemplate;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;/**
* @author huxingnan
* @date 2018/4/11 14:05
*/@Configuration // 自动配置@EnableCaching //启用Spring cachepublic class CacheConfig { // 注释掉的 是我自己 分别配置几种缓存的时候用的 spring ioc 中只能有一个 CacheManager 实列,如果 有多个会报错。
//@Bean// public CacheManager guavaCacheManager() {// GuavaCacheManager cacheManager = new GuavaCacheManager();// cacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterWrite(3600, TimeUnit.SECONDS).maximumSize(1000));// return cacheManager;// }//// @Bean// public CacheManager cacheManager(RedisTemplate
测试对象Account
@Data@AllArgsConstructor@NoArgsConstructorpublic class Account { private String id; private String userName; private String passWord; @DateTimeFormat(pattern = "yyy-MM-dd") private Date createTime; private String alias; private Integer level; private Boolean vip;
}
AccountService
/**
* @author huxingnan
* @date 2018/4/12 13:17
*/@Servicepublic class AccountServiceImpl implements AccountService { @Override
@CachePut(value = CacheConstant.EHCACHE_A,key = "#account.id") public Account saveAccount(Account account) {
System.out.println("保存成功"+account);
account.setId("999");
account.setCreateTime(new Date()); return account;
} @Override
@Cacheable(value = CacheConstant.EHCACHE_A,key = "#account.id") public Account getAccountById(Account account) {
Account account1 = new Account(account.getId(),"zhangfei","zf12345",new Date(),"张飞",2,false); return account1;
} @Override
@Cacheable(value = CacheConstant.EHCACHE_A,key="#account.userName") public List getAccountList(Account account) {
List accountList = Lists.newArrayList();
accountList.add(new Account("124","zhaoyun","zy9999",new Date(),"赵云",3,true));
accountList.add(new Account("125","lvbu","zy9999",new Date(),"吕布",3,true));
System.out.println("查询accountList"+account); return accountList;
} @Override
@CacheEvict(value = CacheConstant.EHCACHE_A,key="#account.id") public int deleteAccountById(Account account) {
System.out.println("删除account"+account); return 1;
} @Override
@CacheEvict(value = CacheConstant.EHCACHE_A,key = "#p0.id") public int updateAccountById(Account account) {
System.out.println("更新account"+account); return 1;
}
}
作者:白袜子先生
链接:https://www.jianshu.com/p/a98796caf536
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2203/viewspace-2802434/ ,如需转载,请注明出处,否则将追究法律责任。