前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(11)SpringBoot整合EhCache做缓存

(11)SpringBoot整合EhCache做缓存

作者头像
IT云清
发布2022-05-07 16:24:00
9890
发布2022-05-07 16:24:00
举报
文章被收录于专栏:IT云清IT云清

   摘要:本文介绍在SpringBoot项目中,如何使用EhCache做缓存。

EhCache 简介:EhCache 是一个纯Java的进程内缓存框架,是Hibernate中默认的CacheProvider;其缓存的数据可以存放在内存里面,也可以存放在硬盘上;其核心是CacheManager,一切Ehcache的应用都是从CacheManager开始的;它是用来管理Cache(缓存)的,一个应用可以有多个CacheManager,而一个CacheManager下又可以有多个Cache;Cache内部保存的是一个个的Element,而一个Element中保存的是一个key和value的配对,相当于Map里面的一个Entry。

它具有如下特点:

  1. 快速
  2. 简单
  3. 多种缓存策略
  4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
  5. 缓存数据会在虚拟机重启的过程中写入磁盘
  6. 可以通过RMI、可插入API等方式进行分布式缓存
  7. 具有缓存和缓存管理器的侦听接口
  8. 支持多缓存管理器实例,以及一个实例的多个缓存区域
  9. 提供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时,会在调用方法之前移除数据。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-04-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.pom.xml
  • 2.启动类添加注解:@EnableCaching
  • 3.配置文件ehcache.xml
  • 4.application.properties
  • 5.web层 UserController.java
  • 6.持久层 UserRepository.java
    • 6.1 @Cacheable()
      • 6.2 @CacheEvict()
        • 6.3 @CachePut()
        • 7.Cache注解详解
        相关产品与服务
        对象存储
        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档