SpringBoot整合缓存1-Ehcache
SpringBoot整合缓存-Ehcache
一、缓存是什么?
缓存是一种将数据临时存储在高速存储介质(如内存)中的技术,目的是减少对数据库等低速存储的访问,提升系统响应速度。
Ehcache 是一个成熟的 Java 缓存框架,支持本地缓存和分布式缓存(需配合 Terracotta 服务器),具备轻量、高效、可配置性强等特点。它是 Spring Cache 默认支持的缓存实现之一,通过 XML 或注解配置缓存策略(如过期时间、最大容量等),可直接与 Spring 生态整合。
二、选择 Ehcache 的优势
- 成熟稳定:作为老牌缓存框架,广泛应用于企业级项目,兼容性强。
- 灵活配置:支持通过 XML 精细定义缓存策略(如堆内 / 堆外存储、过期规则)。
- 本地缓存优先:无需额外部署服务(如 Redis),适合单体应用或对分布式缓存需求较低的场景。
- 与 Spring 无缝整合:通过 Spring Cache 注解即可快速使用,无需手动编写缓存逻辑。
三、案例实现过程

以「图书管理系统」为例,实现图书信息的增删改查,并通过 Ehcache 缓存高频查询数据(如图书详情),减少数据库访问次数。
核心需求:查询图书时优先从缓存获取,新增 / 更新图书时同步更新缓存,删除图书时清除对应缓存。
1. 技术栈
- SpringBoot 2.7.x:快速开发框架,简化配置
- Ehcache 2.x:Java 本地缓存框架,支持自定义缓存策略(过期时间、容量等)
- MyBatis-Plus 3.5.x:MyBatis 增强工具,简化 CRUD 操作
- MySQL:关系型数据库(提供建表 SQL)
2.创建 Maven 项目Ehcache-Demo,配置 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yqd</groupId>
<artifactId>Ehcache-Demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Ehcache-Demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 缓存抽象层 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Ehcache 2.x 缓存实现 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok(简化实体类) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. 配置文件
(1)Ehcache 配置(src/main/resources/ehcache.xml)
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!-- 磁盘缓存位置(可选,本地缓存溢出时使用) -->
<diskStore path="java.io.tmpdir/ehcache"/>
<!-- 默认缓存配置(可选,未指定缓存策略时使用) -->
<defaultCache maxEntriesLocalHeap="1000"
eternal="false"
timeToIdleSeconds="60"
timeToLiveSeconds="60"
overflowToDisk="false"/>
<!-- 图书缓存策略(需与@CacheConfig的cacheNames对应) -->
<cache name="bookCache"
maxEntriesLocalHeap="200"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="60"
overflowToDisk="false"/>
</ehcache>
(2)应用配置(src/main/resources/application.yml)
spring:
# 数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/book_cache_demo?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: root # 替换为你的MySQL用户名
password: 123456 # 替换为你的MySQL密码
# 缓存配置(指定Ehcache)
cache:
type: ehcache
ehcache:
config: classpath:ehcache.xml # 加载自定义缓存策略
# MyBatis-Plus配置
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # Mapper.xml路径
type-aliases-package: com.yqd.entity # 实体类包路径
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL,验证缓存是否生效
(3)SQL脚本
-- 创建数据库
CREATE DATABASE IF NOT EXISTS book_cache_demo DEFAULT CHARACTER SET utf8;
-- 使用数据库
USE book_cache_demo;
-- 创建图书表
CREATE TABLE `t_book` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '图书ID',
`book_name` varchar(100) NOT NULL COMMENT '图书名称',
`author` varchar(50) NOT NULL COMMENT '作者',
`publish_time` date DEFAULT NULL COMMENT '出版时间',
`price` decimal(10,2) NOT NULL COMMENT '价格',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='图书表';
4. 代码实现
(1)实体类(com.yqd.entity.Book.java)
package com.yqd.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@TableName("t_book") // 对应数据库表t_book(MyBatis-Plus已配置table-prefix: t_)
public class Book {
@TableId(type = IdType.AUTO)
private Long id;
private String bookName; // 图书名称(对应数据库book_name)
private String author; // 作者
private Date publishTime; // 出版时间
private BigDecimal price; // 价格
}
(2)Mapper 接口(com.yqd.mapper.BookMapper.java)
package com.yqd.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yqd.entity.Book;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BookMapper extends BaseMapper<Book> {
// 无需手动编写CRUD方法,BaseMapper已提供(selectById、insert、updateById、deleteById等)
}
(3)Service 层(com.yqd.service.BookService.java)
package com.yqd.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yqd.entity.Book;
import com.yqd.mapper.BookMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
@CacheConfig(cacheNames = "bookCache") // 绑定ehcache.xml中的bookCache
public class BookService extends ServiceImpl<BookMapper, Book> {
// 查询图书:缓存key=bookCache::id
@Cacheable(key = "#id")
public Book getById(Long id) {
System.out.println("【数据库查询】id=" + id); // 用于验证缓存是否生效
return baseMapper.selectById(id);
}
// 新增图书:缓存key=bookCache::新增图书的id
@CachePut(key = "#result.id")
public Book add(Book book) {
baseMapper.insert(book);
return book;
}
// 更新图书:缓存key=bookCache::book.id
@CachePut(key = "#book.id")
public Book update(Book book) {
baseMapper.updateById(book);
return book;
}
// 删除图书:清除bookCache::id的缓存
@CacheEvict(key = "#id")
public void delete(Long id) {
baseMapper.deleteById(id);
}
// 清除所有缓存
@CacheEvict(allEntries = true)
public void clearAll() {
System.out.println("【清除所有缓存】");
}
}
(4)Controller 层(com.yqd.controller.BookController.java)
package com.yqd.controller;
import com.yqd.entity.Book;
import com.yqd.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
// 查询图书
@GetMapping("/{id}")
public Book get(@PathVariable Long id) {
return bookService.getById(id);
}
// 新增图书
@PostMapping
public Book add(@RequestBody Book book) {
return bookService.add(book);
}
// 更新图书
@PutMapping
public Book update(@RequestBody Book book) {
return bookService.update(book);
}
// 删除图书
@DeleteMapping("/{id}")
public String delete(@PathVariable Long id) {
bookService.delete(id);
return "删除成功";
}
// 清除所有缓存
@DeleteMapping("/clear")
public String clear() {
bookService.clearAll();
return "所有缓存已清除";
}
}
(5)启动类(com.yqd.EhcacheDemoApplication.java)
package com.yqd;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching // 开启Spring缓存功能
@MapperScan("com.yqd.mapper") // 扫描Mapper接口
public class EhcacheDemo {
public static void main(String[] args) {
SpringApplication.run(EhcacheDemo.class, args);
}
}
四、测试过程(使用 apipost或浏览器)
1. 新增图书
-
请求:
POST http://localhost:8080/books -
Body(JSON):
{ "bookName": "Java编程思想", "author": "Bruce Eckel", "publishTime": "2007-06-01", "price": 108.00 } -
响应:返回新增的图书信息(包含自增 ID,例如
id=1)。
2. 测试查询缓存
- 首次查询:
GET http://localhost:8080/books/1- 控制台输出:
【数据库查询】id=1(走数据库)。 - 响应:返回图书信息。
- 控制台输出:
- 再次查询:
GET http://localhost:8080/books/1- 控制台无输出(走缓存)。
- 响应:返回相同图书信息,速度更快。
3. 测试缓存更新
-
更新图书:
PUT http://localhost:8080/books-
Body(JSON):
{ "id": 1, "bookName": "Java编程思想(第4版)", "author": "Bruce Eckel", "publishTime": "2007-06-01", "price": 128.00 }
-
-
查询验证:
GET http://localhost:8080/books/1- 响应:返回更新后的价格(128.00),说明缓存已同步更新。
4. 测试缓存过期
-
等待 60 秒(ehcache.xml 中配置的
timeToLiveSeconds=60)。 -
再次查询:
GET http://localhost:8080/books/1- 控制台重新输出:
【数据库查询】id=1(缓存过期,重新查库)。
- 控制台重新输出:
5. 测试缓存删除
-
删除图书:
DELETE http://localhost:8080/books/1 -
查询验证:
GET http://localhost:8080/books/1- 响应:
null(数据库记录已删除,缓存也被清除)。
- 响应:
6. 测试清除所有缓存
- 新增另一本图书(例如
id=2),并查询确保缓存生效。 - 清除缓存:
DELETE http://localhost:8080/books/clear - 查询
id=2的图书:控制台输出【数据库查询】id=2(缓存已被清除)。
五、预期结果
- 首次查询走数据库,后续查询走缓存(无数据库日志)。
- 更新操作后,缓存同步更新为新数据。
- 缓存过期或删除后,查询重新走数据库。
- 清除所有缓存后,所有查询均重新走数据库。

浙公网安备 33010602011771号