SpringBoot整合缓存1-Ehcache

news/2025/10/24 18:15:07/文章来源:https://www.cnblogs.com/smalldong/p/19163996

一、缓存是什么?

缓存是一种将数据临时存储在高速存储介质(如内存)中的技术,目的是减少对数据库等低速存储的访问,提升系统响应速度。

Ehcache 是一个成熟的 Java 缓存框架,支持本地缓存分布式缓存(需配合 Terracotta 服务器),具备轻量、高效、可配置性强等特点。它是 Spring Cache 默认支持的缓存实现之一,通过 XML 或注解配置缓存策略(如过期时间、最大容量等),可直接与 Spring 生态整合。

二、选择 Ehcache 的优势

  1. 成熟稳定:作为老牌缓存框架,广泛应用于企业级项目,兼容性强。
  2. 灵活配置:支持通过 XML 精细定义缓存策略(如堆内 / 堆外存储、过期规则)。
  3. 本地缓存优先:无需额外部署服务(如 Redis),适合单体应用或对分布式缓存需求较低的场景。
  4. 与 Spring 无缝整合:通过 Spring Cache 注解即可快速使用,无需手动编写缓存逻辑。

三、案例实现过程

image-20251024180917975

以「图书管理系统」为例,实现图书信息的增删改查,并通过 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.Driverurl: jdbc:mysql://localhost:3306/book_cache_demo?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: root  # 替换为你的MySQL用户名password: 123456  # 替换为你的MySQL密码# 缓存配置(指定Ehcache)cache:type: ehcacheehcache: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,验证缓存是否生效

4. 代码实现

(1)实体类(com.example.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.example.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.example.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.example.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 {@Autowiredprivate BookService bookService;// 查询图书@GetMapping("/{id}")public Book get(@PathVariable Long id) {return bookService.getById(id);}// 新增图书@PostMappingpublic Book add(@RequestBody Book book) {return bookService.add(book);}// 更新图书@PutMappingpublic 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.example.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(缓存已被清除)。

五、预期结果

  • 首次查询走数据库,后续查询走缓存(无数据库日志)。
  • 更新操作后,缓存同步更新为新数据。
  • 缓存过期或删除后,查询重新走数据库。
  • 清除所有缓存后,所有查询均重新走数据库。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/945577.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【开题答辩全过程】以 M11289生鲜商城为例,具备答辩的问题和答案

【开题答辩全过程】以 M11289生鲜商城为例,具备答辩的问题和答案pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "…

如何在一台 Linux 机器上管理不同版本的 CMake

目录🧩 为什么需要多版本 CMake?✅ 核心原则📦 步骤 1:下载并安装多个 CMake 版本(推荐预编译包)1.1 创建安装目录1.2 下载预编译二进制包1.3 复制到目标目录🔗 方法一:使用 update-alternatives 管理(推荐…

90 天打造可持续交付:12 条 DevOps 实践要点与避坑

DevOps 不是工具堆砌,而是“从需求到价值”的系统工程。本文用可量化指标(DORA)作为牵引,给出12 项关键实践与90 天落地路线图,并示例如何用 ONES 研发管理平台把需求、任务、测试、发布与复盘串成一条可追踪的价…

CSharp: word,excel,powerpoint convert to pdf,hrml etc using Aspose.Office

/// <summary>/// 目标文件类型/// Aspose是商业软件需要购买/// </summary>public enum FileFormat{None,Pdf,Html,Text,Doc,Docx,Xls,Xlsx,CSV,PPT,PPTx,SVG,Webp,Rtf,Dwg,Psd}/// <summary>/// 文…

Offsec Nibbles CTF 实战解析:PostgreSQL漏洞利用与权限提升

本文详细记录了Offsec Nibbles CTF挑战的完整解题过程,重点分析了PostgreSQL CVE-2022-1552漏洞的利用方法,通过Python脚本实现远程代码执行,并分享了权限提升的实战经验,最后讨论了系统加固建议。Offsec Nibbles …

Linux基础——iptables常规操作

Linux基础——iptables常规操作一、iptables概述iptables 的核心是四表五链,四表:raw, connecting tracking, mangle, nat 五链:PREOUTING, INPUT, FORWAED, OUTPUT, POSTROUTING 每种表可以包含的链种类TablesPRER…

MySQLdump 常用参数说明 - 实践

MySQLdump 常用参数说明 - 实践2025-10-24 18:04 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importa…

2025 10 24日报

上午 写了周作业的F题,一开始以为很难,后面发现字符串的长度小于等于100,于是就可以直接设 dp[i,j,k], 表示 [1∼i] 里面有 j 个 1,总贡献为 k 的方案中与 s [1∼i] 最小的不同个数,然后转移就很明显了dp[i,j,k]…

Linux手动安装最新版 CMake

目录🔽 步骤 1:进入临时目录并下载 CMake 二进制包🔧 步骤 2:解压安装包🧩 步骤 3:将 CMake 添加到系统 PATH方法 A:全局生效(需 root 权限)方法 B:仅对当前用户生效(无 root 权限也可用)✅ 步骤 4:验…

2025年新疆喀纳斯旅游服务权威推荐榜单:新疆/阿勒泰/禾木深度游旅行社综合评测

碧蓝的喀纳斯湖倒映着雪山林海,三湾的晨雾缭绕如仙境,图瓦村落的木屋错落于林间,这片北疆雪域明珠正吸引着越来越多游客的目光。 据新疆文旅厅数据显示,2024年新疆接待游客总量突破2.5亿人次,但随之而来的是投诉量…

一天一款实用的AI工具,第9期,AI转黏土风格

一键将图片转成黏土风格,呈现立体质感与柔和色彩的可爱画面。工具介绍 本期推荐这款【AI转黏土风格】工具,它能将任何照片瞬间变成软萌圆润的黏土动画风! 它完美模拟了真实黏土的柔和质感与磨砂纹理,让人物如同定制…

题解:P8930 「TERRA-OI R1」神,不惧死亡

$O(m \sqrt[3]{\frac{n^2}{m}log^2{n}})$P8930 「TERRA-OI R1」神,不惧死亡 大水紫 首先发现是神秘区间问题,考虑支持区间操作的数据结构。 发现数据范围是 \(1e5\) ,而且维护的东西很神秘,直接考虑分块或莫队。 如…

生产环节最容易出问题的三个点,老板必须盯紧

之前我们企业在做大之前,生产靠的是人盯人。订单少的时候还能勉强跑得动,一旦订单量起来,问题就暴露出来了:计划排不准,执行乱套,质量失控。 在企业规模升级的那几年,我学到了很多,总结起来,生产环节最容易出…

CS50ai: week2 Uncertainty我的笔记A版 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025 OSCAR丨与创新者同频!Apache RocketMQ 邀您共赴开源之约

10 月 28 日,北京将迎来开源行业的一场重磅盛会——2025 OSCAR 开源产业大会。 本次大会汇聚全球开源领域的思想领袖、技术专家、企业高管以及创新实践者,围绕开源技术的未来、产业创新及生态协同展开深度讨论。 大会…

2025年PSA制氮设备厂家权威推荐榜单:电解水制氢设备/氦气纯化系统/氘气回收纯化源头厂家精选

在现代工业生产中,氮气作为重要的保护性气体,广泛应用于电子、化工、食品、医药等多个领域。PSA(Pressure Swing Adsorption,变压吸附)制氮设备因其高效节能、操作简便的特点,已成为工业气体分离技术中的重要一环…

解决git clone只有master分支的问题

解决git clone只有master分支的问题clone code: git clone git@gitlab.xxx.yy:zzz/IPM_Semantic.git 在使用 git clone + 远程仓库地址将项目下载下来之后,倘若远程仓库有多个分支,会发现,使用git branch查看本地分…

一文读懂循环神经网络(RNN):原理、局限与LSTM解决方案 - 指南

一文读懂循环神经网络(RNN):原理、局限与LSTM解决方案 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "C…

2025年搬家纸箱权威推荐榜单:物流包装/电商纸箱/平口纸箱源头厂家精选

在物流搬运、家庭搬迁及电商包装领域,纸箱作为不可或缺的包装材料,其质量直接关系到物品的安全与搬运效率。面对市场上琳琅满目的纸箱产品,选择一家可靠的供应商成为许多企业与个人消费者的关键任务。本文基于实地考…