基于springboot的第三方缓存设置
引入缓存的依赖包,在配置 pom.xml 文件中添加
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>net.sf.ehcachegroupId>
<artifactId>ehcacheartifactId>
dependency>
创建 .xml 文件,配置缓存内容
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="java.io.tmpdir/Tmp_EhCache"/>
<defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="true" diskPersistent="true" timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
<cache
name="myCache"
eternal="false"
maxElementsInMemory="200"
overflowToDisk="false"
diskPersistent="true"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
memoryStoreEvictionPolicy="LRU"/>
ehcache>
cache中属性的解释:
- name: 缓存名称
- eternal: true表示对象永不过期,此时会忽略timeToIdleSeconds和>- timeToLiveSeconds属性,默认为false
- timeToIdleSeconds: 设定允许对象处于空闲状态的最长时间,以秒为单位。当对象自从最近一次被访问后,如果处于空闲状态的时间超过了timeToIdleSeconds属性值,这个对象就会过期,>- EHCache将把它从缓存中清空。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地处于空闲状态
- timeToLiveSeconds: 设定对象允许存在于缓存中的最长时间,以秒为单位。当对象自从被存放到缓存中后,如果处于缓存中的时间超过了 timeToLiveSeconds属性值,这个对象就会过期,>- EHCache将把它从缓存中清除。只有当eternal属性为false,该属性才有效。如果该属性值为0,则表示对象可以无限期地存在于缓存中。timeToLiveSeconds必须大于timeToIdleSeconds属性,才有意义
- maxElementsInMemory: 内存中最大缓存对象数;maxElementsInMemory界限后,会把溢出的对象写到硬盘缓存中。注意:如果缓存的对象要写入到硬盘中的话,则该对象必须实现了Serializable接口才行
- memoryStoreEvictionPolicy: 当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)
- maxElementsOnDisk: 硬盘中最大缓存对象数,若是0表示无穷大
- overflowToDisk: 是否保存到磁盘,当系统宕机时
- diskPersistent: 是否缓存虚拟机重启期数据,是否持久化磁盘缓存,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为index的文件,这个文件中存放了已经持久化在磁盘中的cache的index,找到后会把cache加载到内存,要想把cache真正持久化到磁盘,写程序时注意执行net.sf.ehcache.Cache.put(Element element)后要调用flush()方法
- diskSpoolBufferSizeMB: 这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
- diskExpiryThreadIntervalSeconds: 磁盘失效线程运行时间间隔,默认为120秒
- clearOnFlush: 内存数量最大时是否清除
在启动类上开启缓存:
/**
* 核心注解文件
*/
@SpringBootApplication
@MapperScan("com.hz.springboot01.mapper")
@EnableCaching //开启缓存
public class SpringBoot01Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot01Application.class, args);
}
}
【读取文件的主配置都是 application.xxx
,只是后缀名用的不一样,内容格式不一样而已】
▶在 application.properties 中读取配置文件 ehcache.xml:
#读取缓存配置文件
spring.cache.ehcache.config=classpath:ehcache.xml
#最后记得开启打印sql语句,方便测试
logging.level.com.hz.dao=debug
▶在 application.yml中读取配置文件 ehcache.xml:
# 读取缓存策略文件
spring:
cache:
ehcache:
config: classpath:ehcache.xml
# mybatis相关配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #SQL控制台输出
cache-enabled: true #开启mybatis的二级缓存
【之前mybatis的时候,开启缓存在 mapper.xml 文件中开启,现在我们是service 中开启,将service实现中方法的返回值进行缓存】
可以标记在一个方法上,也可以标记在一个类上。
当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来
,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。
value:指定哪个缓存
key:如果用相同缓存名称,使用key来区别不同的缓存空间,缓存不共享
condition:指过滤条件,选择谁缓存或者不缓存
@Cacheable //执行默认策略
public User find(Integer id) {}
@Cacheable("myCache1")//Cache是发生在ehcache.xml中myCache1上的
public User find(Integer id) {
....
}
@Cacheable({"cache1", "cache2"})//Cache是发生在ehcache.xml中cache1和cache2上的
public User find(Integer id) {
.....
}
//自定义策略是指我们可以通过Spring的EL表达式来指定我们的key
//#id指参数id作为key
@Cacheable(value="myCache1", key="#id")
public User find(Integer id) {
...
}
//#p0标识第一个参数作为key
@Cacheable(value="myCache1", key="#p0")
public User find(Integer id) {
.....
}
//#user.user_id表示对象user属性user_id作为key
@Cacheable(value="myCache1", key="#user.user_id")
public User find(User user) {
.....
}
@Cacheable(value="myCache1", key="#p0.user_id")
public User find(User user) {
.....
}
//表示只有当user的id为偶数时才会进行缓存
@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
public User find(User user) {
...
}
前面配置与书写代码完成后,可以使用上次的springboot项目添加缓存进行测试。
【关于分页的缓存:参数过多,所以就直接使用它默认】
@Service
public class ProviderServiceImpl implements ProviderService {
@Autowired
private ProviderMapper providerMapper;
@Cacheable("myCache") //使用缓存
public List<Provider> providerInfoList(String proName, String startTime, String endTime, Integer page, Integer limit) {
//计算偏移量
int pyl = (page-1)*limit;
return providerMapper.providerInfoList(proName,startTime,endTime,pyl,limit);
}
}
注意:在实体类实现一下序列化,否则会报一个错误(程序正常运行)
缓存成功!!!
Spring还为我们提供了一个root对象可以用来生成key
示例 | 描述 |
---|---|
root.methodName | 当前方法名 |
root.method.name | 当前方法 |
root.target | 当前被调用的对象 |
root.targetClass | 当前被调用的对象的class |
root.args[0] | 当前方法参数组成的数组 |
root.caches[0].name | 当前被调用的方法使用的Cache |
使用@CachePut时我们可以指定的属性跟@Cacheable是一样的
@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中
一般用于增删改上。。。可以指定的属性有value、key、condition、allEntries、beforeInvocation
//如果不指定key,会清除所有"myCache"的缓存
@CacheEvict(value="myCache",key="#p0.user_id")
public int updUser(SfUser user) throws Exception {
return sfUserMapper.updUser(user);
}
@CacheEvict(value="users", allEntries=true)
public void delete(Integer id) {
System.out.println("delete user by id: " + id);
}
allEntries
:
- allEntries是boolean类型,表示是否需要清除缓存中的所有元素。
- 默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key,删除所有缓存,下次执行的时候会重新加入。
- 有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率