赞
踩
Spring框架支持透明地向应用程序添加缓存对缓存进行管理,其管理缓存的核心是将缓存应用于
操作数据的方法,从而减少操作数据的执行次数,同时不会对程序本身造成任何干扰。
Spring Boot继承了Spring框架的缓存管理功能,通过使用@EnableCaching注解开启基于注解的缓存支持,Spring Boot就可以启动缓存管理的自动化配置。
接下来针对Spring Boot支持的默认缓存管理进行讲解
使用创建的springbootdata的数据库,该数据库有两个表t_article和t_comment
(1)在Dependencies依赖选择项中添加SQL模块中的JPA依赖、MySQL依赖和Web模块中的Web依赖
(2)编写数据库表对应的实体类,并使用JPA相关注解配置映射关系
- package com.lagou.pojo;
-
- import javax.persistence.*;
-
- @Entity(name = "t_comment") // 使用这种方式,那么我么在编写原生sql语句的时候就不在需要添加,nativeQuery = true这个属性
- /* @Entity
- @Table(name = "t_comment") 使用这种方式配置映射实体类,当我们编写原生sql语句进行查询时,我们就必须要加上nativeQuery = true这个属性,否则会报错
- */
- public class Comment {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Integer id;
- private String content;
- private String author;
- @Column(name = "a_id")
- private Integer aId;
-
- @Override
- public String toString() {
- return "Comment{" +
- "id=" + id +
- ", content='" + content + '\'' +
- ", author='" + author + '\'' +
- ", aId=" + aId +
- '}';
- }
-
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public String getAuthor() {
- return author;
- }
-
- public void setAuthor(String author) {
- this.author = author;
- }
-
- public Integer getaId() {
- return aId;
- }
-
- public void setaId(Integer aId) {
- this.aId = aId;
- }
- }
(3)编写数据库操作的Repository接口文件
- package com.lagou.repository;
-
- import com.lagou.pojo.Comment;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.data.jpa.repository.Modifying;
- import org.springframework.data.jpa.repository.Query;
- import org.springframework.transaction.annotation.Transactional;
-
-
- public interface CommentRepository extends JpaRepository<Comment, Integer> {
- // 根据评论id修改评论作者author
- @Transactional
- @Modifying // update操作需要加上此注解
- @Query(value = "update t_comment c set c.author = ?1 where c.id=?2", nativeQuery = true)
- public int updateComment(String author, Integer id);
- }
-
(4)编写service层
- package com.lagou.service;
-
- import com.lagou.pojo.Comment;
- import com.lagou.repository.CommentRepository;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.stereotype.Service;
-
- import java.util.Optional;
-
- @Service
- public class CommentService {
- @Autowired
- private CommentRepository commentRepository;
-
- /**
- * @Cacheable: 将该方法查询结果comment存放在SpringBoot默认缓存中
- * cacheNames: 起一个缓存的命名空间,对应缓存的唯一标识
- * value:缓存结果 key:默认只有一个参数的情况下,key值默认就是方法参数值; 如果没有参数或者多个参数的情况:会使用SimpleKeyGenerate来为生成key
- */
- @Cacheable(cacheNames = "comment")
- public Comment findCommentById(Integer id) {
- Optional<Comment> byId = commentRepository.findById(id);
- if (byId.isPresent()) {
- Comment comment = byId.get();
- return comment;
- }
- return null;
- }
- }
(5)编写Controller层
- package com.lagou.controller;
-
- import com.lagou.pojo.Comment;
- import com.lagou.service.CommentService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- @RestController
- public class CommentController {
- @Autowired
- private CommentService commentService;
- @RequestMapping(value = "/findCommentById")
- public Comment findCommentById(Integer id) {
- Comment comment = commentService.findCommentById(id);
- return comment;
- }
- }
(6)编写配置文件
在项目全局配置文件application.properties中编写对应的数据库连接配置
- # MySQL数据库连接配置
- spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
- spring.datasource.username=root
- spring.datasource.password=root
- #显示使用JPA进行数据库查询的SQL语句
- spring.jpa.show-sql=true
- #开启驼峰命名匹配映射
- mybatis.configuration.map-underscore-to-camel-case=true
- #解决乱码
- spring.http.encoding.force-response=true
(7)测试
上图情况,是因为没有在Spring Boot项目中开启缓存管理。在没有缓存管理的情况下,虽然数据表中的数据没有发生变化,但是每执行一次查询操作(本质是执行同样的SQL语句),都会访问一次数据库并执行一次SQL语句
在前面搭建的Web应用基础上,开启Spring Boot默认支持的缓存,体验Spring Boot默认缓存的使用效果
(1)使用@EnableCaching注解开启基于注解的缓存支持
- package com.lagou;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cache.annotation.EnableCaching;
-
- @SpringBootApplication
- @EnableCaching // 开启springboot基于注解的缓存管理支持
- public class SpringCacheApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(SpringCacheApplication.class, args);
- }
-
- }
(2)使用@Cacheable注解对数据操作方法进行缓存管理。将@Cacheable注解标注在Service类的查询方法上,对查询结果进行缓存
- // 根据评论id查询评论信息
- @Cacheable(cacheNames = "comment")
- public Comment findById(int comment_id){
- Optional<Comment> optional = commentRepository.findCommentById(comment_id);
- if(optional.isPresent()){
- return optional.get();
- }
- return null;
- }
上述代码中,在CommentService类中的findCommentById(int comment_id)方法上添加了查询缓存注解@Cacheable,该注解的作用是将查询结果Comment存放在Spring Boot默认缓存中名称为comment的名称空间(namespace)中,对应缓存唯一标识(即缓存数据对应的主键k)默认为方法参数comment_id的值
(3)测试访问
可以看出,再次 执行findCommentById()方法正确查询出用户评论信息Comment,在配置了SpringBoot默认注解后,重复进行同样的查询操作,数据库只执行了一次SQL查询语句,说明项目开启的默认缓存支持已经生效
刚刚通过使用@EnableCaching、@Cacheable注解实现了Spring Boot默认的基于注解的缓存管理,除此之外,还有更多的缓存注解及注解属性可以配置优化缓存管理
@EnableCaching是由spring框架提供的,springboot框架对该注解进行了继承,该注解需要配置在类上(在中,通常配置在项目启动类上),用于开启基于注解的缓存支持
@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 |
目标方法执行完之后生效, @CachePut被使用于修改操作比较多,哪怕缓存中已经存在目标值了,但是这个注解保证这个方法依然会执行,执行之后的结果被保存在缓存中
@CachePut注解也提供了多个属性,这些属性与@Cacheable注解的属性完全相同。
更新操作,前端会把id+实体传递到后端使用,我们就直接指定方法的返回值从新存进缓存时的key="#id" , 如果前端只是给了实体,我们就使用key="#实体.id" 获取key. 同时,他的执行时机是目标方法结束后执行, 所以也可以使用 key="#result.id" , 拿出返回值的id
@CacheEvict注解是由Spring框架提供的,可以作用于类或方法(通常用在数据删除方法上),该注解的作用是删除缓存数据。@CacheEvict注解的默认执行顺序是,先进行方法调用,然后将缓存进行清除。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。