版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章SpringBoot与缓存第7章SpringBoot与缓存7.1JCache(JSR-107)规范7.2
缓存抽象与缓存注解7.3EhCache2.x缓存7.4Redis缓存27.1JCache(JSR-107)规范缓存在数据访问量比较大的系统中用的还是非常多的,为了统一缓存的开发规范,提升系统的扩展性,J2EE发布了JSR-107规范。1.什么是JSR-107规范JSR是JavaSpecificationRequests的缩写,意思是Java规范提案,2012年10月26日JSR规范委员会发布了JSR107(JCacheAPI)。JCache规范定义了一种对Java对象临时在内存中进行缓存的方法,包括对象的创建、共享访问、假脱机(spooling)、失效、各JVM的一致性等,可被用户缓存最经常访问的数据。37.1JCache(JSR-107)规范
JavaCaching定义了5个核心接口,具体如下:(1)CachingProvider:定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期间访问多个CachingProvider。(2)CacheManager:定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。(3)Cache:是一个类似Map的数据结构并临时存储以key为索引的值。一个Cache仅被一个CacheManager所拥有。(4)Entry:是一个存储在Cache中的key-value对。(5)Expiry:每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。47.1JCache(JSR-107)规范
2.应用调用缓存应用首先会先调用CachingProvider(缓存提供者),缓存提供者管理了多个CacheManager(缓存管理器),缓存管理器中才是真正的Cache缓存。缓存管理器中可以管理不同类型的缓存,比如Redis、EhCache等。在具体缓存组件中,我们还可以设置不同模块的缓存,比如Redis中我们可以来缓存商品信息、热点数据等不同模块数据,每个缓存都是Entry<K,V>键值对类型,并且可以对缓存设置Expiry过期时间,指定缓存存活时间,如图7-1所示。JSR-107作为一个Java规范,它定义的都是一些接口,类似于JDBC规范。直接面向接口编程,需要用到哪种缓存的实现,我们来直接引入该缓存实现即可,系统就能运行起来,使用JSR-107时需引入如下依赖。5<dependency><groupId>javax.cache</groupId><artifactId>cache-api</artifactId></dependency>7.2缓存抽象与缓存注解
1.Spring缓存抽象Spring框架从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口,提供对缓存功能的声明,能够与多种流行的缓存实现集成。SpringCache不是具体的缓存技术,而是基于具体的缓存产品(如EhCache、Redis等)的共性进行了一层抽象,可以通过简单的配置切换底层使用的缓存。Spring定义了自己缓存抽象用于统一缓存操作,仅仅提供抽象,而不是具体实现,只要实现Cache和CacheManager接口,就可以接入Spring通过缓存注解的方式使用缓存(一些主流的缓存都提供该抽象的实现)。
67.2缓存抽象与缓存注解缓存抽象中定义Cache和CacheManager两个接口如下:
Cache:缓存接口,组件规范定义,包含缓存的各种操作集合。Spring提供了各种xxxCache的实现,如RedisCache,EhCacheCache,ConcurrentMapCache等。
CacheManager:缓存管理器,管理各种缓存组件(Cache),简单来说就是用于存放cache,Spring默认也提供了一系列管理器的实现。
抽象的核心是将缓存应用于Java方法,从而减少基于缓存中可用信息的执行次数。每次调用需要缓存功能的方法时,Spring会检查指定参数和指定目标方法是否已经被调用过,如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并将缓存结果返回给用户,下次直接从缓存获取。
77.2缓存抽象与缓存注解2.Spring缓存注解使用SpringCache需要我们做两方面的事,一是声明某些方法使用缓存,二是配置Spring对Cache的支持。Spring对Cache的支持有基于注解和基于XML配置两种方式,下面针对SpringBoot中的缓存注解及相关属性讲解。(1)@Cacheable(2)@CachePut(3)@CacheEvict(4)@Caching(5)@CacheConfig(6)@EnableCaching87.2缓存抽象与缓存注解(1)@Cacheable:该注解是由Spring框架提供,可作用于类或方法(一般标注在service层,通常用在数据查询方法上),用于对方法的查询结果进行缓存存储。@Cacheable注解的执行顺序是,先进行缓存查询,如果为空则进行方法查询,并将结果进行缓存;如果缓存中有数据,不进行方法查询,而是直接使用缓存数据。@Cacheable注解提供了多个属性,用于对缓存存储进行相关配置,具体属性及说明如表。9属性名说明value/cacheNames指定缓存空间的名称,必配属性,这两个属性二选一使用key指定缓存数据的key,默认使用方法参数值,可用SpEL表单式keyGenerator指定缓存数据的key的生成器,与key属性二选一使用cacheManager指定缓存管理器cacheResolver指定缓存解析器,与cacheManager属性二选一使用condition指定在符合某条件下,进行数据缓存unless指定在符合某条件下,不进行数据缓存Sync指定是否使用异步缓存,默认值为false7.2缓存抽象与缓存注解(2)@CachePut:该注解是由Spring框架提供的,可以作用于类或方法(一般标注在service层,通常用在数据更新方法上),作用是更新缓存数据。@CachePut注解的执行顺序是,先进行方法调用,然后将方法结果更新到缓存中。@CachePut注解也提供了多个属性,这些属性与@Cacheable注解的属性完全相同。(3)@CacheEvict:该注解由Spring框架提供的,可以作用于类或方法(一般标注在service层,通常用在数据删除方法上),作用是删除数据缓存。@CacheEvict注解的执行顺序是,先进行方法调用,然后清除缓存。@CacheEvict注解提供了多个属性,与@Cacheable注解的属性基本相同。除此之外,还提供了两个特殊属性:
allEntries、beforeinvocation。107.2缓存抽象与缓存注解(4)@Caching:该注解用于同时添加多个缓存注解,定义复杂规则的数据缓存。该注解作用于类或者方法。@Caching注解包含cacheable、put和evict三个属性,作用等于@Cacheable、@CachePut和@CacheEvict。(5)@CacheConfig:该注解作用于类,用于统筹管理类中所有使用@Cacheable、@CachePut和@CacheEvict注解标注的方法中的公共属性,这些公共属性包括cacheNames、keyGenerator、cacheManager和cacheResolver。(6)@EnableCaching:该注解是Spring框架提供的,SpringBoot框架对该注解进行了继承,用于开启基于注解的缓存支持,该注解需要配置类上(在SpringBoot中,通常配置在项目的启动类上)。117.2缓存抽象与缓存注解3.SpringBoot支持的缓存组件在SpringBoot中,数据的管理存储依赖于Spring框架中cache相关的org.springframework.cache.Cache和org.springframework.cache.CacheManager缓存管理接口。如果程序中没有定义类型为CacheManager的Bean组件或者名为cacheResolver的CacheResolver缓存解析器,SpringBoot将根据以下指定的顺序尝试并启用以下缓存组件。Generic、JCache(JSR-107)(EhCache3、Hazelcast、Infinispan等)、EhCache2.x、Hazelcast、Infinispan、Couchbase、Redis、Caffeine、Simple。在项目中添加某个缓存管理组件(例如EhCache2.x)后,SpringBoot项目会选择并启用对应的缓存管理器。127.2缓存抽象与缓存注解
如果项目中同时添加了多个缓存组件,且没有指定缓存管理器或者缓存解析器(CacheManager或者CacheResolver),那么SpringBoot会按照上述顺序在添加的多个缓存中优先启用指定的缓存组件进行缓存管理。SpringBoot默认缓存管理中,没有添加任何缓存管理组件能实现缓存管理。这是因为开启缓存管理后,SpringBoot会按照上述列表顺序查找有效的缓存组件进行缓存管理,如果没有任何缓存组件,会默认使用最后一个Simple缓存组件进行管理。Simple缓存组件是SpringBoot默认的缓存管理组件,它默认使用内存中的ConcurrentHashMap进行缓存存储,所以在没有添加任何第三方缓存组件的情况下,也可以实现内存中的缓存管理。在默认情况下使用的是Simple简单缓存,不建议在正式环境中使用这种缓存管理方式。137.2缓存抽象与缓存注解4.SprigBoot默认缓存管理Spring框架支持透明地向应用程序添加缓存并对缓存进行管理,其管理缓存的核心是将缓存应用于操作数据的方法中,从而减少操作数据的次数,同时不会对程序本身造成任何干扰。SpringBoot继承了Spring的缓存管理功能,通过@EnableCaching注解开启基于注解的缓存支持,自动化配置合适的缓存管理器(CacheManager)。下面针对SpringBoot支持的默认缓存管理,结合数据库的访问操作对SpringBoot的缓存管理进行讲解,步骤如下。(1)使用MySQL数据库创建一个名为chapter07的数据库,并新建user数据表,包含id、username、password属性,预先插入几条测试记录。147.2缓存抽象与缓存注解(2)新建一个SpringBoot工程chapter07cache,Group和Packagename为com.yzpc,在Dependencies依赖中选择Web节点下的SpringWeb依赖,SQL节点下的SpringDataJPA依赖、MySQLDriver依赖和I/O节点下的Springcacheabstraction依赖,单击Finish按钮,如图7-2所示。pom.xml中自动添加的依赖代码,如下所示。(3)在项目的src/main/resources/路径下的application.properties配置文件中加入数据库连接配置信息(与5.2.1小节中介绍的一致),接下来设置JPA的基本配置以及Springcache的目标缓存管理器配置,配置如下所示。(4)在项目的src/main/java/路径下的com.yzpc包中,新建一个pojo包,并在该包中新建与数据表user对应的实体类User,添加JPA对应的注解进行映射配置,代码如下所示。15<!--开启cache缓存--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><!--省略SpringWeb、SpringDataJPA、MySQLDriver依赖代码-->spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/chapter07?serverTimezone=UTCspring.datasource.username=rootspring.datasource.password=123456spring.jpa.database=mysqlspring.jpa.show-sql=truespring.jpa.hibernate.ddl-auto=update#Springcache目标缓存管理器默认为simple,如果不加,会按顺序查找到该缓存组件spring.cache.type=simplepackagecom.yzpc.pojo;importjavax.persistence.*;@Entity(name="user")
//
设置ORM实体类,并指定映射的表名publicclassUserimplementsSerializable{
@Id//表示映射对应的主键//设置主键自增策略
@GeneratedValue(strategy=GenerationType.AUTO)
privateintid;
privateStringusername;
privateStringpassword;
//此处省略构造方法
//此处省略相应属性的setter/getter方法
//重写toString方法}}(5)在项目的src/main/java/路径下的com.yzpc包中,新建一个repository包,并在该包中新建一个用于操作User实体的接口UserRepository,该接口继承自JpaRepository,也可在该接口中,自己定义相应的方法,代码如下所示。
(6)在项目的src/main/java/路径下的com.yzpc包中,新建一个service包,并在该包中新建一个用于User相关业务操作的UserService类,代码如下所示。(7)在项目的src/main/java/路径下的com.yzpc包中,新建一个controller包,并在该包中新建一个访问控制类UserController,代码如下所示。
16publicinterfaceUserRepositoryextendsJpaRepository<User,Integer>{}@ServicepublicclassUserService{
@Autowired
UserRepositoryuserRepository;
//根据id查询用户信息
@Cacheable(cacheNames="user",unless="#result==null")
publicUserfindUserById(intid){
Optional<User>user=userRepository.findById(id);
if(user.isPresent()){
returnuser.get();}
returnnull;}}@RestControllerpublicclassUserController{
@Autowired
UserServiceuserService;
@GetMapping("/findUserById")
publicUserfindUserById(intid){
Useruser=userService.findUserById(id);
returnuser;}}7.2缓存抽象与缓存注解7.2缓存抽象与缓存注解(8)在项目的Chapter07cacheApplication启动类上使用@EnableCaching注解开启基于注解的缓存支持,内容如下所示。(9)启动项目,访问http://localhost:8080/findUserById?id=3,查询id为3的用户信息,调用方法查询数据库,并将查询结果数据存储到缓存user中,页面查询结果如图7-3所示。此时控制台输出Hibernate的查询语句,如图7-4所示。再次访问http://localhost:8080/findUserById?id=3,此时控制台没有任何输出内容,但页面还是输出前面的查询结果,这表明没有调用查询方法,页面的数据直接从数据缓存中获得。17@SpringBootApplication@EnableCaching//开启SpringBoot基于注解的缓存管理支持publicclassChapter07cacheApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(Chapter07cacheApplication.class,args);}}7.3EhCache2.x缓存EhCache是一种广泛使用的开源的高性能Java分布式缓存框架,有很高的拓展性和伸缩性,广泛使用在各种Java项目中(如Hibernate默认使用Ehcache作为二级缓存)。在SpringBoot中,只要配置一个配置文件就可以将EhCache集成到项目中。EhCache2.x缓存的使用步骤如下。(1)复制7.2小节的chapter07cache项目并重命名为chapter07ehcache。用IDEA打开该项目,选择chapter07ehcache项目,点击,选择Refactor
Rename命令,然后输入新的Module名称为chapter07ehcache,单击OK按钮,如图7-5所示。打开pom.xml文件,修改<artifactId>和<name>标签下的名称为chapter07ehcache。187.3EhCache2.x缓存
右击启动类Chapter07cacheApplication,选择Refactor
Rename命令,修改新名称为Chapter07ehcacheApplication,如图7-6所示,在图7-6中,单击Refactor按钮,在弹出的RenameTests对话框中,选中class前面的复选框,通知修改测试类,单击OK按钮,如图7-7所示。
单击Run菜单下“EidtConfigurations…”选项,在弹出的对话框中,将Name后名称修改为Chapter07ehcacheApplication,单击“OK”按钮,如图所示。(2)在pom.xml文件中,添加Ehcache2.x缓存依赖坐标,内容如下所示。通过配置属性spring.cache.type来指定缓存管理器,修改perties配置文件,添加代码如下。19<!--此处省略其它依赖代码--><!--ehcache的缓存坐标--><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId></dependency>#Springcache目标缓存管理器修改为ehcachespring.cache.type=ehcache7.3EhCache2.x缓存
(3)在项目的src/main/resources/目录下创建ehcache.xml文件,作为Ehcache缓存的配置文件,配置如下所示。这是一个常规的Ehcache配置文件,提供两个缓存策略,一个是默认的,另一个名为user。
(4)修改UserRepository接口,添加一个修改方法update(),并在方法上方添加@Query注解,代码如下所示。
(5)修改UserService类,在该类中添加增删改查的方法,分别为save()、delete()、update()、findOne()方法,在相应的方法上加上缓存注解,代码如下所示。20<?xmlversion="1.0"encoding="UTF-8"?><ehcache><diskStorepath="java.io.tmpdir/cache"/><defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"/><cachename="user"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="600"/></ehcache>publicinterfaceUserRepositoryextendsJpaRepository<User,Integer>{
@Transactional@Modifying@Query("updateuserusetu.username=?1,u.password=?2whereu.id=?3")
publicvoidupdate(Stringusername,Stringpassword,intid);}1
@Cacheable(cacheNames="user",unless="#reult==null")
publicUserfindOne(intid){
Optional<User>u=userRepository.findById(id);
System.out.println("为Key="+u.get().getId()+"的数据做了缓存");
returnu.get();}
@CachePut(value="user",key="#result.id")
publicUsersave(Useruser){
Useru=userRepository.save(user);
System.out.println("为Key="+u.getId()+"的数据做了缓存");
returnu;}@CachePut(value="user",key="#result.id")
publicUserupdate(Useruser){
userRepository.update(user.getUsername(),user.getPassword(),user.getId());
System.out.println("为key="+user.getId()+"数据记录做了缓存");
returnuser;}
@CacheEvict(value="user")
publicvoiddelete(intid){
System.out.println("删除了Key="+id+"的数据缓存");}7.3EhCache2.x缓存
(6)修改UserController类,在该类中添加相应增删改查方法并添加访问映射,代码如下所示。(7)启动项目,第一次访问http://localhost:8080/findOne?id=4,将调用方法查询数据库。并将数据存储到缓存,此时控制台输出如图7-6所示,同时网页显示数据如图7-7所示。
再次访问http://localhost:8080/findOne?id=4,此时控制台没有任何输出,这表明没有调用查询方法,页面显示的数据是直接从缓存中获取的。
21
@GetMapping("/findOne")
publicUserfindOne(intid){
returnuserService.findOne(id);}
@GetMapping("/save")
publicUsersave(Useruser){
returnuserService.save(user);}
@GetMapping("/update")
publicUserupdate(Useruser){
Useru=userService.update(user);
returnu;}
@GetMapping("/delete")
publicStringdelete(intid){
userService.delete(id);
return"删除key="+id+"的数据缓存";}7.3EhCache2.x缓存访问http://localhost:8080/save?username=lisi&password=lisi,此时控制台输出如图7-8所示,页面显示数据如图7-9所示。插入数据后,访问http://localhost:8080/findOne?id=5,控制台无任何输出,从缓存直接获得id为5的数据,页面显示结果与图7-9相同。
访问http://localhost:8080/update?id=5&username=李四&password=123456,此时控制台输出如图7-10所示,页面显示数据如图7-11所示。修改数据后,访问http://localhost:8080/findOne?id=5,控制台无任何输出,从缓存直接获得id为5的数据,页面显示结果与图7-11相同。227.3EhCache2.x缓存访问http://localhost:8080/delete?id=5,删除key为5的缓存,控制台和浏览器都输出“删除key=5的数据缓存”。再次访问http://localhost:8080/findOne?id=5,此时重新做了缓存,控制台输出结果如图7-12所示。237.4Redis缓
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 水利工程项目类保险方案与费率
- 《数字地形测量学》本科题集
- 南充-PEP-24年小学四年级英语第五单元寒假试卷
- 小学语文大单元任务群教学设计思路及实施策略
- 强化学校管理-全面落实科学发展观
- 2024年项目投资与资产管理服务项目资金筹措计划书代可行性研究报告
- 【上海54】第一次月考B卷(考试版+解析)
- 赏识教育心得体会
- 讲文明演讲稿300字(33篇)
- 24.5 相似三角形的性质(第3课时)同步练习
- 2024齐齐哈尔市职工大学教师招聘考试笔试试题
- 2024年急性胰腺炎急诊诊治专家共识解读课件
- 浙江省【小升初】2023年小升初数学试卷及答案【各地真题】
- 2024年NOC初赛-Scratch(小学高年级组)试题及答案
- MOOC 中医体质学-新乡医学院 中国大学慕课答案
- 【课件】丹纳赫DBS-问题解决培训
- 浙江省宁波市小升初数学真题重组卷
- 火电厂信息化建设规划方案
- 技改项目报告
- “中信泰富”事件的反思
- 工业机器人系统运维知识竞赛题库及答案(100题)
评论
0/150
提交评论