(11)SpringBoot整合EhCache做缓存
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
摘要:本文介绍在SpringBoot项目中,如何使用EhCache做缓存。
EhCache 简介:EhCache 是一个纯Java的进程内缓存框架,是Hibernate中默认的CacheProvider;其缓存的数据可以存放在内存里面,也可以存放在硬盘上;其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的;它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache;Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。
它具有如下特点:
- 快速
- 简单
- 多种缓存策略
- 缓存数据有两级:内存和磁盘,因此无需担心容量问题
- 缓存数据会在虚拟机重启的过程中写入磁盘
- 可以通过RMI、可插入API等方式进行分布式缓存
- 具有缓存和缓存管理器的侦听接口
- 支持多缓存管理器实例,以及一个实例的多个缓存区域
- 提供Hibernate的缓存实现
注意:本文案例使用的接口层,持久层等,都依赖于(5)SpringBoot使用JPA访问数据库,并在其基础上添加了部分方法,完整源码请点击阅读原文,github同步更新代码。
在SpringBoot项目中整合EhCache做缓存,具体步骤如下:
1.pom.xml
我们在pom.xml中引入相关依赖:
2.启动类添加注解:@EnableCaching
启动类加此注解后,会自动开启SpringBoot对缓存的支持
3.配置文件ehcache.xml
在resources包下新建一个ehcache.xml配置文件,用于配置ehcache缓存的参数,我这里习惯在resources下再建一个resource文件夹,专门存放配置文件,所以我这里的结构是:main\resources\resource\ehcache.xml
各个参数的涵义如下:
- name:缓存名称。
- maxElementsInMemory:缓存最大个数。
- eternal:对象是否永久有效,一但设置了,timeout将不起作用。
- timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
- timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
- overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
- diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
- maxElementsOnDisk:硬盘最大缓存个数。
- diskPersistent:是否缓存虚拟机重启期数据,默认为false。
- diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
- memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用),有如下3种清空策略:
- - FIFO ,first in first out (先进先出)。
- - LFU , Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit 值最小的将会被清出缓存。
- - LRU ,Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
- clearOnFlush:内存数量最大时是否清除。
4.application.properties
由于SpringBoot已经为我们内置了redis,jcache等多种缓存,所以我们需要在application.properties文件中配置选择一下;且本示例持久层为jpa,所以我们顺便控制台输出一下sql,方便后面观察。
5.web层 UserController.java
由于此案例持久层使用的是之前写过的JpaRepository,web层是直接调用的持久层的,这里为了直观一些,我把web层做了简单的修改,这里再贴一下代码,后面会直接贴访问路径,访问的就是这个类的接口,方法均见名知意。
6.持久层 UserRepository.java
我们在需要使用缓存的持久层,添加@CacheConfig(),然后在需要缓存的方法上添加对应的缓存注解。此次案例我们在以下方法做简单测试:
然后,我们逐个调用接口,进行分析。
6.1 @Cacheable()
在findUserByUserName,findById两个方法上,我们都添加了@Cacheable(key = "#p0");这里用了@Cacheable()的一个参数key,缓存对象存储时的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = "#p0"):意思是使用此函数第一个参数作为该缓存的key值,如果有第二个参数,我们也可以用key = "#p1";
我们这里调用这两个方法时,会根据这个key先去缓存找是否有数据,如果有,就直接返回了,如果没有,那就会去数据库查询后返回,并以此key为key,存入缓存中;当再次调用此方法时,若该缓存没有过期,那么当此方法的参数和这个key相同时,就会直接去找缓存;我们可以在控制台查看打印的sql来观察是否访问数据库。
分页方法上,我们添加了@Cacheable(key = "#p0.pageNumber"),此时执行http://localhost:8088/user/findByPage?pageSize=10&pageNum=3,会发现有sql执行,第二次时,没有sql执行;我们把pageNumber换为13,发现就有sql执行了,因为我们这里缓存时key只和pageNumber有关;如果pageNumber=3,把pageSize=50呢?会发现尽管参数变了,但是这次依旧走的缓存,没有查数据库,因为,我们这里设置的key和pageSize是无关的,pageNum找到了,就直接返回了。
6.2 @CacheEvict()
此注解通常用在删除方法上,用于从缓存中清除数据。
我们这里访问http://localhost:8088/user/findById?id=1599991,第一次访问时发现会有sql显示,第二次就没有sql了,因为缓存中已经有了这个id为key的数据了,直接走的缓存;
如果deleteById方法上没有@CacheEvict注解时,那我们执行http://localhost:8088/user/deleteById?id=1599991,会发现数据库此数据删除了,但是http://localhost:8088/user/findById?id=1599991时,发现还是查出来了,为什么呢?因为我们之前查询过,此数据被缓存了,而且没有过期,所以我们查询时走缓存还是可以拿出来的。
如果我们在deleteById方法上加上@CacheEvict(key = "#p0"),那http://localhost:8088/user/deleteById?id=1599991执行后,数据库数据会被删除,再去http://localhost:8088/user/findById?id=1599991,会发现查询不出来了,因为我们删除执行后,把缓存中key为1599991的缓存数据删除了,所以缓存中再查询时查不到了。
6.3 @CachePut()
此注解通常用在新增和修改方法上,根据条件,进行缓存。
我们执行一下http://localhost:8088/user/addUser,比如被加到数据库的User.userName=momo456,在addUser方法上,@CachePut(key = "#p0.userName"),我们会在数据库添加完User后,在缓存中也添加一份数据,key为momo456;此时,我们去执行http://localhost:8088/user/findByUserName?userName=momo456,会发现,尽管我们是第一次查询,但是控制台并没有显示sql语句,说明此请求并没有向数据库发送请求,而是直接走的缓存。
7.Cache注解详解
- @CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置。在这里@CacheConfig(cacheNames = "user"):配置了该数据访问对象中返回的内容将存储于名为user的缓存对象中,我们也可以不使用该注解,直接通过@Cacheable自己配置缓存集的名字来定义。
- @Cacheable:在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。阅读源码,发现该注解主要有下面几个参数:
- - value、cacheNames:两个等同的参数(cacheNames为Spring 4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring 4中新增了@CacheConfig,因此在Spring 3中原本必须有的value属性,也成为非必需项了。
- - key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = "#p0"):使用函数第一个参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档。
- - condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有当第一个参数的长度小于3的时候才会被缓存,读者可自行实验尝试。
- - unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。
- - keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的。
- - cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用。
- - cacheResolver:用于指定使用哪个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。
- @CachePut:配置于函数上,能够根据参数定义条件来进行缓存,它与@Cacheable不同的是,它每次都会真是调用函数,所以主要用于数据新增和修改操作上。它的参数与@Cacheable类似,具体功能可参考上面对@Cacheable参数的解析。
- @CacheEvict:配置于函数上,通常用在删除方法上,用来从缓存中移除相应数据。除了同@Cacheable一样的参数之外,它还有下面两个参数:
- - allEntries:非必需,默认为false。当为true时,会移除所有数据。
- - beforeInvocation:非必需,默认为false,会在调用方法之后移除数据。当为true时,会在调用方法之前移除数据。
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |