当前位置:   article > 正文

SpringBoot的缓存机制_springboot缓存机制

springboot缓存机制

SpringBoot的缓存机制

SpringBoot 3.1中开始对缓存提供支持,核心思想是对方法的缓存,当开发者调用一个方法是,将方法的数和返回值作为Key/Value形式缓存起来。再次调用该方法时,如果缓存中有数据,就从缓存中直接拿取数据,否则再去执行该方法,但是,SpringBoot并未提供缓存的实现,而是提供一套缓存的API,使开发者可以自由的选择选择缓存的实现方法,SpringBoot支持的缓存有一下几种:

JCache(JSP-107)
EhCahe 2.x
Hazelcast
Infinispan
Couchbase
Redis
Caffeine
Simple

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

本章我们将介绍EhCahe 2.x 和 Redis,由于Spring早已将缓存领域统一,因此无论使用哪种缓存实现,不同的只是缓存配置,一般使用的缓存注解都是一致的(Spring的缓存注解和各种缓存实现的关系就像JDBC和各种数据库驱动的关系一样)

EhCahe 2.x

EhCahe 2.x 缓存在java开发领域早已久负盛名,在SpringBoot中,值需要一个配置文件就可以将EhCahe集成到项目中,EhCahe 2.x 操作步骤如下:

1. 创建项目添加缓存依赖

创建SpringBoot项目,添加spring-boot-starter-cache 依赖以及EhCahe 依赖,

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2. 添加缓存配置文件

如果EhCahe的缓存存在,并且classpath下有一个名为ehcache.xml的EhCahe文件,那么EhCacheCacheManager将会自动作为缓存的实现,因此,在resources目录下创建ehcache.xml文件作为EhCahe缓存的配置文件,代码如下:

<eacache>
    <diskStore path="java.io.temdir/cache"/>
    <defaultCache maxElemensInMemory="10000"
    		  eternal="false"
    		  timeToIdleSeconds="120"
    		  timeLiveleSeconds="120"
    		  overflowTpDisk="false"
    		  diskPersistent="false"
    		  diskExpirtyThreadIntervalSeconds="120"/>
     <cache name="book_cache"
		  maxElemensInMemory="10000"
        	  eternal="true"
        	  timeToIdleSeconds="120"
        	  timeLiveleSeconds="120"
        	  overflowTpDisk="true"
        	  diskPersistent="true"
        	  diskExpirtyThreadIntervalSeconds="600"/>
<eacache>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这是一个常规的EhCahe配置文件,提供了两个缓存策略一个是默认的,另一个则是book_cache。其中,name表示缓存名称;maxElemensInMemory 表示缓存的最大个数;eternal表示缓存对象师傅永久有效,一旦设置了永久有效,timeoyt将不起作用;timeToIdleSeconds 表示缓存对象在失效前的闲置时间(单位:秒) 当eternal=false 对象不是永久有效时该属性才会生效;timeLiveleSeconds 表示缓存对象在失效前允许存活的时间(单位:秒),当eternal=false 对象不是永久有效,该属性才会生效;overflowTpDisk标书内存中的数量达到maxElemensInMemory时,EhCahe是否将数据写到磁盘中;diskExpirtyThreadIntervalSeconds表示磁盘失效的运行时间隔,还有好多的属性,这里就不一一介绍了,另外,如果开发者想自定义EhCahe配置文件的名称和位置,可以在application.properties中配置:

spring.cache.ehcache.config=classpath:config/another-config.xml
  • 1

3. 开启缓存

在项目的入口类上添加上@EnableCaching注解开启缓存,代码如下:

@Spring BootApplication
@EnableCaching
public class CacheApplicatiion{	
	public static void main (String[] args){
		SpringApplication.run(CacheApplication.class, args);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4. 创建BookDao

创建Book实体类,代码如下:

public class Book implements Serializable{
	private Integer id;
	private String name;
	private String auyhor;
	// 省略get/set
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

5. 创建BookService

创建BookService类和BookDao,代码如下:

@Repository
@CacheConfig(cacheNames = "book_cache")
public class BookDao{
	@Cacheable
	public Book getBookById(Integer id){
		System.out.println(getBookBuId);
		Book book = new Book();
		book,setid(id);
		book.setName("肖申克的救赎");
		book.author("斯蒂芬·埃德温·金");
		return book;
	}
	@CachePut(key = "#book.id")
	public Book updateBookById(Book book){
	System.out.println(updateBookBuId);
	book.setName("肖申克的救赎2");
	return book;
	}
	@CacheEvict(key = "#id")
	public void deleteBookById(Integer id){
	System.out.println(deleteBookBuId);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

以上的实体类和Dao层以及Service层不多做解释;

使用root对象生成key,见下表:

  	| 属性名称 		| 属性描述 			| 用法实例
  	| methodName 		| 当前方法名			| #root.methodName
       	| method            	| 当前方法对象          		| #root.method.name
  	| cache   		| 当前方法使用的缓存  		| #root.cache[0].name
  	| target   		| 当前被调用的对象 		| #root.target
  	| targetClass   	| 当前被调用对象的class 		| #root.targetClass
  	| args   		| 当前方法参数数据 		| #root.args[0]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如果这些key不能满足开发需求,也可以自定义缓存key的生成器KeyCenerator 代码如下:

@Component
public class MyKeyCenerator implements KeyCenerator{
	@Override
	public Object generate(Object target, Methor methor, Object... params){
		return Arrays.toString(params);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
@Service
@CacheConfig(cacheName = "book_cache")
public class BookDao{
	@Autowired
	MyKeyCenerator myKeyCenerator;

	@Cacheable(keyCenerator = "myKeyCenerator")
	public Book getBookById(Integer id){
	System.out.println(getBookBuId);
	Book book = new Book();
  	book,setid(id);
  	book.setName("肖申克的救赎3");
  	book.author("斯蒂芬·埃德温·金");
  
	return book;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

代码解释

自定义MyKeyCenerator实现KeyCenerator接口,当然实现该接口中的generate方法,该方法的三个参数分别是当前对象,当前请求的方法以及方法的参数,也可以根据这些信息组成一个新的key返回返回值就是缓存的key,第13行在@Cacheable注解中引用MyKeyCenerator即可;

第13行@CachePut 注解般用 于数据更新方法上, 与@Cacheable注解不同,添加了第13行@CachePut 注解般用 于数据更新方法上, 与@Cacheable注解不同,添加了后将方法的执行结果缓存起来,如果该key对应的数据已经被缓存起来了,就会覆盖之前的数据,这样可以避免再次加载数据时获取到脏數据.同时,@CachePut具有和Cacheable类似的属性,这里不再赘述。

第19行@CacheEvict注解-般用于删除方法上,表示移除一个她y对应的缓存CatheErie注解有两个特殊的属性: alEntries和bfrelnvocation,其中lnlries表示是否将所有的缓存数据都移除,默认为false, beforeInvocation表示是否在方法执行之前移除缓存中的数据,默认为false, 即在方法执行之后移除缓存中的数据。

6. 创建测试类

创建测试类,对service层的代码进行测试,代码如下:

@RunWith(SpringRunner.class)
@Spring BootTest
public class CacheApplicationTeats{
	@Autowired
	BookDao bookDao;

	@Text
	public void contextLoads(){
	bookDao.getBookById(1);
	bookDao.getBookById(1);
	bookDao.deleteBookById(1);
	Book book = bookDao.getBookById(1);
	System.out.println("book:" + book);
	Book book1 = new Book();
	book1.setName("肖申克的救赎");
	book1.setauthor("斯蒂芬·埃德温·金");
	book1.setId(1);
	bookDao.updateBookById(book1);
	Book book2 = bookDao.getBookById(1);
	System.out.println("book2:" + book2);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

执行会在控制台将你在方法里存储的值输出

一开始执行 了两个查询,但是查询方法只打印了一次,因为第二次使用了缓存。接下来执行了删除方法,删除方法执行完之后再次执行查询,查询方法又被执行了,因为在删除方法中缓存已经被删除了。再接下来执行更新方法,更新方法中不仅更新数据,也更新了缓存,所以在最后的查询方法中,查询方法日志没打印,说明该方法没执行,而是使用了缓存中的数据,而缓存中的数据已经被更新了。

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

闽ICP备14008679号