当前位置:   article > 正文

SpringBoot缓存管理

springboot缓存管理

1、默认缓存管理

Spring框架支持透明地向应用程序添加缓存对缓存进行管理,其管理缓存的核心是将缓存应用于
操作数据的方法,从而减少操作数据的执行次数,同时不会对程序本身造成任何干扰。

Spring Boot继承了Spring框架的缓存管理功能,通过使用@EnableCaching注解开启基于注解的缓存支持,Spring Boot就可以启动缓存管理的自动化配置。

接下来针对Spring Boot支持的默认缓存管理进行讲解

 

2、基础环境搭建

2.1、准备数据

使用创建的springbootdata的数据库,该数据库有两个表t_article和t_comment

2.2、创建项目,功能编写

(1)在Dependencies依赖选择项中添加SQL模块中的JPA依赖、MySQL依赖和Web模块中的Web依赖

(2)编写数据库表对应的实体类,并使用JPA相关注解配置映射关系

  1. package com.lagou.pojo;
  2. import javax.persistence.*;
  3. @Entity(name = "t_comment") // 使用这种方式,那么我么在编写原生sql语句的时候就不在需要添加,nativeQuery = true这个属性
  4. /* @Entity
  5. @Table(name = "t_comment") 使用这种方式配置映射实体类,当我们编写原生sql语句进行查询时,我们就必须要加上nativeQuery = true这个属性,否则会报错
  6. */
  7. public class Comment {
  8. @Id
  9. @GeneratedValue(strategy = GenerationType.IDENTITY)
  10. private Integer id;
  11. private String content;
  12. private String author;
  13. @Column(name = "a_id")
  14. private Integer aId;
  15. @Override
  16. public String toString() {
  17. return "Comment{" +
  18. "id=" + id +
  19. ", content='" + content + '\'' +
  20. ", author='" + author + '\'' +
  21. ", aId=" + aId +
  22. '}';
  23. }
  24. public Integer getId() {
  25. return id;
  26. }
  27. public void setId(Integer id) {
  28. this.id = id;
  29. }
  30. public String getContent() {
  31. return content;
  32. }
  33. public void setContent(String content) {
  34. this.content = content;
  35. }
  36. public String getAuthor() {
  37. return author;
  38. }
  39. public void setAuthor(String author) {
  40. this.author = author;
  41. }
  42. public Integer getaId() {
  43. return aId;
  44. }
  45. public void setaId(Integer aId) {
  46. this.aId = aId;
  47. }
  48. }

(3)编写数据库操作的Repository接口文件 

  1. package com.lagou.repository;
  2. import com.lagou.pojo.Comment;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. import org.springframework.data.jpa.repository.Modifying;
  5. import org.springframework.data.jpa.repository.Query;
  6. import org.springframework.transaction.annotation.Transactional;
  7. public interface CommentRepository extends JpaRepository<Comment, Integer> {
  8. // 根据评论id修改评论作者author
  9. @Transactional
  10. @Modifying // update操作需要加上此注解
  11. @Query(value = "update t_comment c set c.author = ?1 where c.id=?2", nativeQuery = true)
  12. public int updateComment(String author, Integer id);
  13. }

(4)编写service层

  1. package com.lagou.service;
  2. import com.lagou.pojo.Comment;
  3. import com.lagou.repository.CommentRepository;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.cache.annotation.Cacheable;
  6. import org.springframework.stereotype.Service;
  7. import java.util.Optional;
  8. @Service
  9. public class CommentService {
  10. @Autowired
  11. private CommentRepository commentRepository;
  12. /**
  13. * @Cacheable: 将该方法查询结果comment存放在SpringBoot默认缓存中
  14. * cacheNames: 起一个缓存的命名空间,对应缓存的唯一标识
  15. * value:缓存结果 key:默认只有一个参数的情况下,key值默认就是方法参数值; 如果没有参数或者多个参数的情况:会使用SimpleKeyGenerate来为生成key
  16. */
  17. @Cacheable(cacheNames = "comment")
  18. public Comment findCommentById(Integer id) {
  19. Optional<Comment> byId = commentRepository.findById(id);
  20. if (byId.isPresent()) {
  21. Comment comment = byId.get();
  22. return comment;
  23. }
  24. return null;
  25. }
  26. }

(5)编写Controller层

  1. package com.lagou.controller;
  2. import com.lagou.pojo.Comment;
  3. import com.lagou.service.CommentService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. @RestController
  8. public class CommentController {
  9. @Autowired
  10. private CommentService commentService;
  11. @RequestMapping(value = "/findCommentById")
  12. public Comment findCommentById(Integer id) {
  13. Comment comment = commentService.findCommentById(id);
  14. return comment;
  15. }
  16. }

(6)编写配置文件

在项目全局配置文件application.properties中编写对应的数据库连接配置

  1. # MySQL数据库连接配置
  2. spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
  3. spring.datasource.username=root
  4. spring.datasource.password=root
  5. #显示使用JPA进行数据库查询的SQL语句
  6. spring.jpa.show-sql=true
  7. #开启驼峰命名匹配映射
  8. mybatis.configuration.map-underscore-to-camel-case=true
  9. #解决乱码
  10. spring.http.encoding.force-response=true

(7)测试

上图情况,是因为没有在Spring Boot项目中开启缓存管理。在没有缓存管理的情况下,虽然数据表中的数据没有发生变化,但是每执行一次查询操作(本质是执行同样的SQL语句),都会访问一次数据库并执行一次SQL语句 

3、默认缓存体验

在前面搭建的Web应用基础上,开启Spring Boot默认支持的缓存,体验Spring Boot默认缓存的使用效果

(1)使用@EnableCaching注解开启基于注解的缓存支持

  1. package com.lagou;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cache.annotation.EnableCaching;
  5. @SpringBootApplication
  6. @EnableCaching // 开启springboot基于注解的缓存管理支持
  7. public class SpringCacheApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(SpringCacheApplication.class, args);
  10. }
  11. }

(2)使用@Cacheable注解对数据操作方法进行缓存管理。将@Cacheable注解标注在Service类的查询方法上,对查询结果进行缓存 

  1. // 根据评论id查询评论信息
  2. @Cacheable(cacheNames = "comment")
  3. public Comment findById(int comment_id){
  4. Optional<Comment> optional = commentRepository.findCommentById(comment_id);
  5. if(optional.isPresent()){
  6. return optional.get();
  7. }
  8. return null;
  9. }

上述代码中,在CommentService类中的findCommentById(int comment_id)方法上添加了查询缓存注解@Cacheable,该注解的作用是将查询结果Comment存放在Spring Boot默认缓存中名称为comment的名称空间(namespace)中,对应缓存唯一标识(即缓存数据对应的主键k)默认为方法参数comment_id的值 

(3)测试访问

可以看出,再次 执行findCommentById()方法正确查询出用户评论信息Comment,在配置了SpringBoot默认注解后,重复进行同样的查询操作,数据库只执行了一次SQL查询语句,说明项目开启的默认缓存支持已经生效 

  • 底层结构:在诸多的缓存自动配置类中, SpringBoot默认装配的是SimpleCacheConfiguration ,他使用的CacheManager 是 ConcurrentMapCacheManager, 使用 ConcurrentMap 当底层的数据结构,按照Cache的名字查询出Cache, 每一个Cache中存在多个k-v键值对,缓存值 

4、缓存注解介绍 

刚刚通过使用@EnableCaching、@Cacheable注解实现了Spring Boot默认的基于注解的缓存管理,除此之外,还有更多的缓存注解及注解属性可以配置优化缓存管理 

4.1、@EnableCaching注解

@EnableCaching是由spring框架提供的,springboot框架对该注解进行了继承,该注解需要配置在类上(在中,通常配置在项目启动类上),用于开启基于注解的缓存支持

4.2、@Cacheable注解

@Cacheable注解也是由spring框架提供的,可以作用于类或方法(通常用在数据查询方法上),用于对方法结果进行缓存存储。注解的执行顺序是,先进行缓存查询,如果为空则进行方法查询,并将结果进行缓存;如果缓存中有数据,不进行方法查询,而是直接使用缓存数据

@Cacheable注解提供了多个属性,用于对缓存存储进行相关配置

属性名说明
value/cacheNames指定缓存空间的名称,必配属性。这两个属性二选一使用
key指定缓存数据的key,默认使用方法参数值,可以使用SpEL表达式
keyGenerator指定缓存数据的key的生成器,与key属性二选一使用
cacheManager指定缓存管理器
cacheResolver指定缓存解析器,与cacheManager属性二选一使用
condition指定在符合某条件下,进行数据缓存
unless指定在符合某条件下,不进行数据缓存
sync指定是否使用异步缓存。默认false

执行流程&时机

方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取,(CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建;去Cache中查找缓存的内容,使用一个key,默认就是方法的参数,如果多个参数或者没有参数,是按照某种策略生成的,默认是使用KeyGenerator生成的,使用SimpleKeyGenerator生成key,SimpleKeyGenerator生成key的默认策略:

参数个数key
没有参数new SimpleKey()
有一个参数参数值
多个参数new SimpleKey(params)

常用的SPEL表达式

描述示例
当前被调用的方法名#root.mathodName
当前被调用的方法#root.mathod
当前被调用的目标对象#root.target
当前被调用的目标对象类#root.targetClass
当前被调用的方法的参数列表#root.args[0] 第一个参数, #root.args[1] 第二个参数...
根据参数名字取出值#参数名, 也可以使用 #p0 #a0 0是参数的下标索引
当前方法的返回值#result

4.3、@CachePut注解

目标方法执行完之后生效, @CachePut被使用于修改操作比较多,哪怕缓存中已经存在目标值了,但是这个注解保证这个方法依然会执行,执行之后的结果被保存在缓存中

@CachePut注解也提供了多个属性,这些属性与@Cacheable注解的属性完全相同。

更新操作,前端会把id+实体传递到后端使用,我们就直接指定方法的返回值从新存进缓存时的key="#id" , 如果前端只是给了实体,我们就使用key="#实体.id" 获取key. 同时,他的执行时机是目标方法结束后执行, 所以也可以使用 key="#result.id" , 拿出返回值的id

4.4、@CacheEvict注解 

@CacheEvict注解是由Spring框架提供的,可以作用于类或方法(通常用在数据删除方法上),该注解的作用是删除缓存数据。@CacheEvict注解的默认执行顺序是,先进行方法调用,然后将缓存进行清除。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/164555
推荐阅读
相关标签
  

闽ICP备14008679号