Ehcache 是一个用 Java 实现的使用简单,高速,实现线程安全的缓存管理类库,Ehcache 提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的 cache 管理方案,采用限制比较宽松的 Apache License V2.0 作为授权方式。Ehcache 从 Hibernate 发展而来,逐渐覆盖了 Cache 界的所有功能,是当前成长趋向不错的一个项目。它具有快速、简单易用、低消耗、强扩展性、依赖性低、支持缓存或元素的失效、支持对象或序列化缓存、支持内存缓存和磁盘缓存、提供了 FIFO、LRU、LFU 缓存策略、采用分布式缓存机制等特点。
添加依赖
在 pom.xml 文件中加入 spring-boot-starter-cache
和 ehcache
依赖包。
1 | <!--spring 的缓存依赖,使用 spring 缓存机制必须加入的依赖--> |
2 | <dependency> |
3 | <groupId>org.springframework.boot</groupId> |
4 | <artifactId>spring-boot-starter-cache</artifactId> |
5 | </dependency> |
6 | |
7 | <!--集成 ehcache 需要的依赖--> |
8 | <dependency> |
9 | <groupId>net.sf.ehcache</groupId> |
10 | <artifactId>ehcache</artifactId> |
11 | </dependency> |
创建 Ehcache 配置文件
在资源文件(resource)目录下创建 ehcache.xml
配置文件,进行 Ehcache 的配置。
1 |
|
2 | |
3 | <ehcache> |
4 | <!--默认的 ehcache 缓存配置--> |
5 | <defaultCache |
6 | eternal="false" |
7 | maxElementsInMemory="1000" |
8 | overflowToDisk="false" |
9 | diskPersistent="false" |
10 | timeToIdleSeconds="0" |
11 | timeToLiveSeconds="600" |
12 | memoryStoreEvictionPolicy="LRU" /> |
13 | |
14 | <!--指定缓存空间名称--> |
15 | <cache name="user" |
16 | maxElementsInMemory="1000" |
17 | eternal="false" |
18 | overflowToDisk="false" |
19 | diskPersistent="false" |
20 | timeToLiveSeconds="5" // 设置缓存有效时间为 5 秒 |
21 | memoryStoreEvictionPolicy="LRU" |
22 | /> |
23 | </ehcache> |
配置 application.properties 文件
在 application.properties 文件中,配置 ehcache.xml 文件的加载路径。
1 | # ehcache 缓存配置 |
2 | classpath:config/ehcache.xml = |
Ehcache 配置文件参数说明
name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsOnDisk:硬盘最大缓存个数。
eternal:对象是否永久有效,一旦设置了,timeout 将不起作用。
overflowToDisk:是否保存到磁盘,当系统宕机时,会存入本地磁盘。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当 eternal=false 对象不是永久有效时使用,可选属性,默认值是 0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。
最大时间介于创建时间和失效时间之间。仅当 eternal=false 对象不是永久有效时使用,默认是 0,也就是对象存活时间无穷大。
diskPersistent:是否缓存虚拟机重启期数据。
diskSpoolBufferSizeMB:这个参数设置 DiskStore(磁盘缓存)的缓存区大小。默认是 30MB。每个 Cache 都应该有自己的一个缓冲区。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是 120 秒。
memoryStoreEvictionPolicy:当达到 maxElementsInMemory 限制时,Ehcache 将会根据指定的策略去清理内存。默认策略是 LRU(最近最少使用)。你可以设置为 FIFO(先进先出)或是 LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
memoryStoreEvictionPolicy:缓存策略,可选策略有:
FIFO(First In First Out),这个是大家最熟的,先进先出。
LFU(Less Frequently Used),就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
LRU(Least Recently Used),最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
开启缓存支持
在 SpringBoot 应用主类上添加 @EnableCaching
开启缓存支持,进行自动扫描。
1 |
|
2 |
|
3 | public class EhcacheApplication { |
4 | |
5 | public static void main(String[] args) { |
6 | SpringApplication.run(EhcacheApplication.class, args); |
7 | } |
8 | } |
准备数据
模拟数据库数据
1 | /** |
2 | * 数据工厂,模拟数据库的数据 |
3 | * |
4 | * @author star |
5 | **/ |
6 | public class DataFactory { |
7 | |
8 | private DataFactory() { |
9 | } |
10 | |
11 | private static List<UserDTO> userDtoList; |
12 | |
13 | static { |
14 | // 初始化集合 |
15 | userDtoList = new ArrayList<>(); |
16 | |
17 | UserDTO user = null; |
18 | for (int i = 0; i < 5; i++) { |
19 | user = new UserDTO(); |
20 | user.setName("star" + i); |
21 | user.setAge(23); |
22 | userDtoList.add(user); |
23 | } |
24 | } |
25 | |
26 | public static List<UserDTO> getUserDaoList() { |
27 | return userDtoList; |
28 | } |
29 | } |
编写业务代码
- 编写 DAO 层
1 | |
2 | /** |
3 | * UserRepository |
4 | * |
5 | * @author star |
6 | */ |
7 |
|
8 | public class UserRepository { |
9 | |
10 | /** |
11 | * 获取用户信息(此处是模拟的数据) |
12 | */ |
13 | public UserDTO getUserByName(String username) { |
14 | UserDTO user = getUserFromList(username); |
15 | return user; |
16 | } |
17 | |
18 | /** |
19 | * 从模拟的数据集合中筛选 username 的数据 |
20 | */ |
21 | private UserDTO getUserFromList(String username) { |
22 | |
23 | List<UserDTO> userDaoList = DataFactory.getUserDaoList(); |
24 | for (UserDTO user : userDaoList) { |
25 | if (Objects.equals(user.getName(), username)) { |
26 | return user; |
27 | } |
28 | } |
29 | return null; |
30 | } |
31 | } |
- 编写 Service 层
1 | /** |
2 | * UserService |
3 | * |
4 | * @author star |
5 | **/ |
6 |
|
7 | "user") (cacheNames = |
8 | public class UserService { |
9 | |
10 | |
11 | private UserRepository userRepository; |
12 | |
13 | "#name") (key = |
14 | public UserDTO getUser(String name) { |
15 | UserDTO user = userRepository.getUserByName(name); |
16 | |
17 | return user; |
18 | } |
19 | } |
由于在上一篇 springboot-cache 已经对缓存用法做了详细说明,这里就简单介绍一下:
@Cacheable
: 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。@CachePut
:配置于方法上时,能够根据参数定义条件来进行缓存,其与 @Cacheable 不同的是,它不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中,所以主要用于数据新增和修改操作上。@CacheEvict
:配置于方法上时,表示从缓存中移除相应数据。编写 Controller 层
1 | /** |
2 | * UserResource |
3 | * |
4 | * @author star |
5 | */ |
6 |
|
7 | "/api") ( |
8 | public class UserResource { |
9 | |
10 | |
11 | private UserService userService; |
12 | |
13 | "/users/{name}") ( |
14 | public ResponseEntity<UserDTO> getUser(@PathVariable("name") String name) { |
15 | UserDTO user = userService.getUser(name); |
16 | |
17 | return ResponseEntity.ok(user); |
18 | } |
19 | } |
演示
通过多次向接口 http://localhost:8080/api/users/star1
GET 数据来观察效果:
可以看到缓存的启用和效果如下所示: