Ehcache配置详解与SpringBoot整合实例

1. 配置

1.1 基本配置

下面基本算是使用Ehcache的xml最简配置了。

1<?xml version="1.0" encoding="UTF-8"?> 2<ehcache name="mycache-manager" updateCheck="false"> 3 <!-- 磁盘缓存位置 --> 4 <diskStore path="java.io.tmpdir/ehcache"/> 5 6 <!-- 默认缓存 --> 7 <defaultCache 8 maxEntriesLocalHeap="1000" 9 eternal="false" 10 timeToIdleSeconds="3600" 11 timeToLiveSeconds="3600" 12 overflowToDisk="false"> 13 </defaultCache> 14 15 <!-- 用户缓存策略 --> 16 <cache name="userCache" 17 maxEntriesLocalHeap="2000" 18 eternal="false" 19 timeToIdleSeconds="600" 20 timeToLiveSeconds="0" 21 overflowToDisk="false" 22 statistics="true"> 23 </cache> 24</ehcache>

1.2 ehcache

每个ehcache对应一个CacheManager,ehcache的name用来配置CacheManager的名称。

可以通过下面的方式获取:

CacheManager cacheManager = CacheManager.getCacheManager("mycache-manager");

1.3 diskStore

diskStore用来配置缓存数据保存的磁盘位置,常用的三个:

  1. user.home:用户主目录
  2. user.dir:用户当前工作目录
  3. java.io.tmpdir:默认临时文件路径

当然也可以使用绝对路径

1.4 defaultCache

默认缓存策略,当Ehcache没有找到缓存策略的时候,就会使用这个缓存策略,只能定义一个默认策略。

1.5 cache配置项

缓存策略,设置缓存超时时间,最大缓存数目等。

配置项

说明

name

缓存的名称,可以通过指定名称获取指定的某个Cache对象

eternal

true,永不过期,超时设置将被忽略,一些静态的配置数据可以设置为true

statistics

是否收集统计信息,如果需要监控缓存使用情况,应该设置为true,默认false,统计对性能有影响

clearOnFlush

内存数量最大时是否清除

overflowToDisk

内存不足时,是用磁盘进行缓存

diskPersistent

是否启用磁盘持久化的机制,JVM重启时可以加载之前缓存,默认值是false

timeToIdleSeconds

对象允许闲置时间,单位秒,超时过期,0表示可以一直空闲

timeToLiveSeconds

缓存数据最多存活时间,0表示不过期,timeToLiveSeconds不等于0时应该大于timeToIdleSeconds

maxElementsOnDisk

磁盘最大缓存多少cache数量

maxElementsInMemory

内存中允许存储的最大的元素个数,0代表无限个

maxEntriesLocalDisk

当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中

maxEntriesLocalHeap

堆内存中最大缓存对象数,0表示没有限制

diskSpoolBufferSizeMB

设置磁盘缓存的缓存区大小,默认是30MB,每个Cache都应该有自己的一个缓冲区

memoryStoreEvictionPolicy

缓存达到maxElementsInMemory限制时,内存缓存过期策略算法,LRU(最近最少使用,默认)、FIFO(先进先出)、LFU(最少访问次数)

diskExpiryThreadIntervalSeconds

检查磁盘缓存数据过期线程运行时间间隔,默认是120秒

1.6 通过编程式配置

1@Test 2public void createCache(){ 3 CacheManager cacheManager = CacheManager.create(); 4 Cache cache = new Cache("cacheName", 1000, true, false, 120, 120); 5 CacheConfiguration config = cache.getCacheConfiguration(); 6 config.setClearOnFlush(true); 7 config.setMaxEntriesLocalHeap(100); 8 cacheManager.addCache(cache); 9}

2. Spring与Ehcache

Spring对缓存的支持,是通过代理实现的,直接通过注解标就可以实现缓存,基本不需要处理太多和缓存相关的逻辑。

Spring的几个缓存相关的注解参数都支持SpEL表达式,下面是几个SpEL常用表达:

属性

位置

说明

示例

args

root

当前方法参数数组

#root.args[0]

method

root

当前方法

#root.method.name

target

root

当前被调用的对象

#root.target

caches

root

当前被调用的方法使用的Cache

#root.caches[0].name

methodName

root

当前方法名

#root.methodName

targetClass

root

当前被调用的对象的class

#root.targetClass

argument

context

当前被调用的参数,saveUser(User user)

#user.id

result

context

当前被调用的返回值

#result

2.1 @Cacheable

用@Cacheable注解的方法表示会缓存改方法的返回值。

当第一次调用这个方法时,方法的返回值会被缓存下来,在缓存的有效时间内,以后访问这个方法都直接返回缓存结果,不再执行方法中的代码段。

@Cacheable参数:

  1. value:缓存策略名称用于查找缓存位置,不能为空,Ehcache就是xml配置的cache的name,说明缓存数据放到哪个Cache中
  2. key:指定缓存使用的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL
  3. condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL

2.2 @CachePut

@CachePut和@Cacheable基本一样,但是它每次都会执行方法。一般用在更新方法上,这样可以同时更新缓存和数据库。

2.3 @CacheEvict

@CacheEvict用来删除缓存数据,它有参数:

  1. value:缓存策略名称用于查找缓存位置,不能为空
  2. key:缓存的key,默认为空
  3. condition:触发条件,只有满足条件的情况才会清除缓存,默认为空
  4. allEntries:是否清除全部缓存,默认为false,true表示清除value指定策略中的全部缓存

3. 实例与测试

3.1 maven依赖

1<dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-web</artifactId> 4</dependency> 5 6<dependency> 7 <groupId>org.springframework.boot</groupId> 8 <artifactId>spring-boot-starter-data-jpa</artifactId> 9</dependency> 10<dependency> 11 <groupId>mysql</groupId> 12 <artifactId>mysql-connector-java</artifactId> 13 <scope>runtime</scope> 14</dependency> 15 16 <!--Spring Boot应用程序提供缓存支持--> 17<dependency> 18 <groupId>org.springframework.boot</groupId> 19 <artifactId>spring-boot-starter-cache</artifactId> 20</dependency> 21 22<!--Ehcache缓存实现--> 23<dependency> 24 <groupId>net.sf.ehcache</groupId> 25 <artifactId>ehcache</artifactId> 26</dependency> 27<!--JSR-107缓存规范--> 28<dependency> 29 <groupId>javax.cache</groupId> 30 <artifactId>cache-api</artifactId> 31</dependency>

依赖中忽略了spring-boot-starter-parent,选择自己喜欢的版本加入:

1<parent> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-parent</artifactId> 4 <version>2.4.1</version> 5</parent>

3.2 spring 配置

1logging.config=classpath:logback.xml 2 3spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 4spring.datasource.url=jdbc:mysql://localhost:3306/data?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 5spring.datasource.username=tim 6spring.datasource.password=123456 7 8spring.jpa.database=MySQL 9spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect 10spring.jpa.show-sql=true 11spring.jpa.hibernate.ddl-auto=update 12 13spring.datasource.hikari.maximum-pool-size=20 14spring.datasource.hikari.minimum-idle=5 15 16spring.cache.jcache.config=classpath:ehcache.xml

3.3 Ehcache配置

1<?xml version="1.0" encoding="UTF-8"?> 2<ehcache name="mycache-manager" updateCheck="false"> 3 4 <!-- 缓存数据磁盘位置 --> 5 <diskStore path="java.io.tmpdir"/> 6 7 <!-- 默认缓存 --> 8 <defaultCache 9 maxEntriesLocalHeap="1000" 10 eternal="false" 11 timeToIdleSeconds="3600" 12 timeToLiveSeconds="3600" 13 overflowToDisk="false"> 14 </defaultCache> 15 16 <!-- 用户缓存策略 --> 17 <cache name="userCache" 18 maxEntriesLocalHeap="2000" 19 eternal="false" 20 timeToIdleSeconds="60" 21 timeToLiveSeconds="120" 22 overflowToDisk="false" 23 diskPersistent="true"> 24 </cache> 25</ehcache>

将diskPersistent设置为true,方便执行不同Test的时候,还保留之前的缓存。

这里使用的是Ehcache的2.x版本,3.x版本做了很多的变化,实现了JSR-107,如果可以尽量选择3.x的版本。

Ehcache配置类:

1@Configuration 2@EnableCaching 3public class EhcacheConfiguration { 4 5 @Bean(name = "ehCacheCacheManager") 6 public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){ 7 return new EhCacheCacheManager(bean.getObject()); 8 } 9 10 @Bean 11 public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){ 12 EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean(); 13 ClassPathResource classPathResource = new ClassPathResource("ehcache.xml"); 14 cacheManagerFactoryBean.setConfigLocation (classPathResource); 15 cacheManagerFactoryBean.setShared(true); 16 return cacheManagerFactoryBean; 17 } 18}

使用@EnableCaching注解开启Spring缓存。

3.4 启动类

1import org.springframework.boot.SpringApplication; 2import org.springframework.boot.autoconfigure.SpringBootApplication; 3import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 4 5@SpringBootApplication 6@EnableJpaRepositories(basePackages = {"vip.mycollege.jpa.mysql.repository"}) 7public class Start { 8 public static void main(String[] args) { 9 SpringApplication.run(Start.class, args); 10 } 11}

3.5 实体类

1import javax.persistence.Column; 2import javax.persistence.Entity; 3import javax.persistence.GeneratedValue; 4import javax.persistence.GenerationType; 5import javax.persistence.Id; 6import javax.persistence.Table; 7import java.io.Serializable; 8 9@Entity 10@Table(name = "user") 11public class User implements Serializable { 12 13 @Id 14 @GeneratedValue(strategy = GenerationType.SEQUENCE) 15 private Integer id; 16 private Integer age; 17 @Column(length = 20) 18 private String name; 19 20 public Integer getId() { 21 return id; 22 } 23 24 public void setId(Integer id) { 25 this.id = id; 26 } 27 28 public Integer getAge() { 29 return age; 30 } 31 32 public void setAge(Integer age) { 33 this.age = age; 34 } 35 36 public String getName() { 37 return name; 38 } 39 40 public void setName(String name) { 41 this.name = name; 42 } 43 44 @Override 45 public String toString() { 46 return "User{" + 47 "id=" + id + 48 ", age=" + age + 49 ", name='" + name + '\'' + 50 '}'; 51 } 52}

实体类要实现Serializable,Ehcache持久化对象到磁盘需要。

3.6 Repository

1import org.springframework.data.repository.CrudRepository; 2import vip.mycollege.jpa.mysql.entity.User; 3 4public interface UserRepository extends CrudRepository<User,Integer> { 5 6}

3.7 缓存逻辑

1import org.springframework.cache.annotation.CacheEvict; 2import org.springframework.cache.annotation.CachePut; 3import org.springframework.cache.annotation.Cacheable; 4import org.springframework.stereotype.Service; 5import vip.mycollege.jpa.mysql.entity.User; 6import vip.mycollege.jpa.mysql.repository.UserRepository; 7 8import javax.annotation.Resource; 9 10@Service 11public class EhcacheService { 12 13 @Resource 14 private UserRepository userRepository; 15 16 @Cacheable(value="userCache", key="'user:' + #id") 17 public User findUserById(Integer id) { 18 System.out.println("execute findUserById"); 19 return userRepository.findById(id).get(); 20 } 21 22 @Cacheable(value="userCache", condition="#id < 3") 23 public User findCacheConditionUserById(Integer id) { 24 System.out.println("execute findCacheConditionUserById"); 25 return userRepository.findById(id).get(); 26 } 27 28 @CacheEvict(value="userCache",key="'user:' + #user.id") 29 public void deleteUser(User user) { 30 System.out.println("execute deleteUser"); 31 userRepository.deleteById(user.getId()); 32 } 33 34 @CacheEvict(value="userCache", allEntries=true) 35 public void deleteAllUserCache() { 36 System.out.println("execute deleteAllUserCache"); 37 System.out.println("delete all cache"); 38 } 39 40 @CachePut(value = "userCache",key = "'user:'+#user.id") 41 public User updateUser(User user) { 42 System.out.println("execute updateUser"); 43 user.setAge(100); 44 userRepository.save(user); 45 return user; 46 } 47}

可以自己生成一些数据,然后用下面的测试类来测试不同缓存的效果。

3.8 测试类

1import org.junit.Test; 2import org.junit.runner.RunWith; 3import org.springframework.boot.test.context.SpringBootTest; 4import org.springframework.test.context.junit4.SpringRunner; 5import vip.mycollege.jpa.mysql.entity.User; 6 7import javax.annotation.Resource; 8 9 10@RunWith(SpringRunner.class) 11@SpringBootTest 12public class EhcacheServiceTest { 13 14 @Resource 15 private EhcacheService ehcacheService; 16 17 @Test 18 public void findUserById() { 19 User user = ehcacheService.findUserById(1); 20 System.out.println(user); 21 } 22 23 @Test 24 public void findCacheConditionUserById() { 25 User user = ehcacheService.findCacheConditionUserById(5); 26 System.out.println(user); 27 } 28 29 @Test 30 public void deleteUser() { 31 User user = new User(); 32 user.setId(1); 33 ehcacheService.deleteUser(user); 34 } 35 36 @Test 37 public void deleteAllUserCache() { 38 ehcacheService.deleteAllUserCache(); 39 } 40 41 @Test 42 public void updateUser() { 43 User user = new User(); 44 user.setId(1); 45 ehcacheService.updateUser(user); 46 } 47}

4. 文档资料

Ehcache2.9文档 Ehcache3.8文档 Ehcache快速开始 Ehcache示例 SpringBoot缓存文档

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )