在纯 JFinal项目中,一键启用阿里 JetCache 多级缓存能力

JetCachePlugin

JetCachePlugin 封装阿里 JetCache,专为 JFinal(纯 Java)打造“一行接入、本地(Caffeine)+远程(Redis)按需开启关闭、cached 风格、到期前可自动刷新缓存、防击穿、高频访问无忧”。

  • JetCachePlugin 在纯 JFinal 或 Java 项目中,一键启用阿里 JetCache 多级缓存能力

🔥 你是否羡慕 Spring 项目能用 JetCache 一个注释就搞定,而 JFinal 却只能手写重复的 put/get 缓存逻辑?

  • 想用 本地 + Redis 多级缓存,但不想引入 Spring?

  • 担心 热点 key 失效导致缓存击穿,DB 被打爆?

  • 厌倦了重复写 if (cache == null) loadFromDB() 的样板代码?

  • 知道 alibaba/jetcache 很强,但被繁琐的接入方案劝退?

现在,这些问题一次性解决!

  • JetCachePlugin —— 将阿里 JetCache 的强大能力,无缝注入 JFinal 项目,一行代码接入!

  • 为什么选择它?—— 站在巨人肩膀上,为 JFinal 而生

优势说明

优势说明
🧠 基于阿里 JetCache 内核底层使用 JetCache 2.7.8+,经过阿里内部及数千企业验证,稳定可靠
🚫 纯 Java 运行通过精简封装,完美契合 JFinal 极简哲学
⚡ 自动多级缓存本地(Caffeine) + 远程(Redis via Lettuce)自动串联,先读快缓存,再读持久缓存
🛡️ 天然防缓存击穿支持 syncLocal = true(默认开启),并发请求同一 miss key 时,仅一个线程查 DB,其余等待结果
🧩 JFinal 风格 APIme.add(new JetCachePlugin("default")) 初始化,JetCacheKit.cached(...)JetCacheKit.get(...)JetCacheKit.put(...) 使用,符合 JFinal 开发者直觉
📦 轻量集成仅依赖 jetcache-core + jetcache-redis-lettuce + caffeine,无额外负担

🚀 快速上手(真的只要一行!)

Step 1:添加 Maven 依赖(via JitPack)

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.github.seallon</groupId>
    <artifactId>jet-cache-plugin</artifactId>
    <version>v1.0.0</version>
</dependency>

💡 实际底层依赖:

  • com.alicp.jetcache:jetcache-core

  • com.alicp.jetcache:jetcache-redis-lettuce

  • com.github.ben-manes.caffeine:caffeine

Step 2:初始化(在 JFinalConfig.configPlugin(Plugins me) 中)

public void configPlugin(Plugins me) {
    me.add(new JetCachePlugin("default")
        //.redisOnly() //仅启用Redis缓存
        //.setLocalLimit(500) //本地缓存(Caffeine)的最大条目数限制
        //.setLocalExpireSeconds(600) //本地缓存(Caffeine)中每个条目的过期时间(秒)
        //.setRemoteExpireSeconds(3600) //远程缓存(Redis)中每个条目的过期时间(秒)
        //.setDefaultCacheConfig(new DefaultCacheConfig(100, 1800L, 3600L, false, 0.2, 120L)) //设置全局默认新建缓存配置
        //.setAutoCreateCache(true) //是否允许在调用时自动创建不存在的缓存实例
        //.enableRandomTtl(300) //是否启用“随机 TTL”功能,用于缓解缓存雪崩问题
        //.setGlobalMinRefreshTtlSeconds(120L) //全局最小自动刷新 TTL
        //.setMaxAllowedTtlSeconds(7*24*3600L) //全局最大允许的缓存 TTL
    );
}

✅ 支持多种模式:

  • JetCachePlugin() → 仅本地缓存(开发/测试)

  • JetCachePlugin("default") → 默认 Redis

  • JetCachePlugin("redis://:pwd@host:6379/2") → 指定 Redis

Step 3:使用缓存(anywhere in your code)

// 手动创建缓存
JetCacheKit.createCache("course");
JetCacheKit.createCache("course", 100, 20, 40);
JetCacheKit.createCache("default", "course", 100, 20, 40);

// ================ 自动走多级缓存 + 防击穿加载 ================

// 1. 带加载器的 cached 风格(开启自动刷新)
CourseInfo courseInfo = JetCacheKit.cached("courseInfo", "1", 
    () -> CourseInfo.dao.queryFirst(Dict.create().eq("id", 1)),
    JetCacheKit.CachedOptions.of().autoRefresh(true)
);

// 2. 带加载器的 cached 风格(指定缓存时间 60s)
CourseInfo courseInfo = JetCacheKit.cached("courseInfo", "1", 60,
    () -> CourseInfo.dao.queryFirst(Dict.create().eq("id", 1))
);

// 3. 使用默认策略
CourseInfo courseInfo = JetCacheKit.cached("courseInfo", "1",
    () -> CourseInfo.dao.queryFirst(Dict.create().eq("id", 1))
);

// 手动写入
JetCacheKit.put("courseInfo", "1", courseInfo);
JetCacheKit.put("courseInfo", "1", courseInfo, 120);

// 手动获取
Object obj = JetCacheKit.get("courseInfo", "1");

// 移除缓存
JetCacheKit.evict("courseInfo", "1");
JetCacheKit.evictAll("courseInfo");

// 同步刷新
JetCacheKit.refresh("courseInfo", "1", () -> ...);
JetCacheKit.refresh("courseInfo", "1", 120, () -> ...);

// 异步刷新
JetCacheKit.refreshAsync("courseInfo", "1", () -> ...);
JetCacheKit.refreshAsync("courseInfo", "1", 120, () -> ...);

// 获取命中率
MetricsSnapshot snap = JetCacheKit.getMetrics("courseInfo");
Console.log("courseInfo cache hit rate: {}%, avg load: {}ms", 
    snap.getHitRate() * 100, snap.getAvgLoadMillis());

// 获取所有缓存命中率
Map<String, MetricsSnapshot> snaps = JetCacheKit.getAllMetrics();

关键机制:JetCachePlugin 默认开启 syncLocal,    即使 1000 个线程同时请求 "123"只有一个线程查数据库,其余线程阻塞等待结果,彻底杜绝雪崩!

🛠 高级能力(JetCache 原生支持)

  • ✅ 自定义序列化(Kryo / Hessian / JSON)

  • ✅ 缓存统计监控(命中率、加载耗时)

  • ✅ 异步刷新(refreshAfterWrite)

  • ✅ 多 Redis 实例支持(通过 URI 指定)

  • ✅ 优雅关闭(纯 Java 调用:JetCacheManager.shutdown()

📊 推荐指数 & 易用指数

维度评分(⭐️ 满分 5 星)说明
推荐指数⭐️⭐️⭐️⭐️⭐️让 JFinal 用户平权享受 JetCache 企业级能力
易用指数⭐️⭐️⭐️⭐️⭐️初始化 1 行,使用 1 行,无学习成本
性能提升⭐️⭐️⭐️⭐️✨本地命中率 >90% 时,QPS 提升 5~10 倍
稳定性⭐️⭐️⭐️⭐️⭐️基于 JetCache 成熟内核,生产验证
兼容性⭐️⭐️⭐️⭐️⭐️JFinal 3.x ~ 5.x,Java 8+,无 Spring 冲突

🌐 开源地址

📣 欢迎 Star、Fork、PR! 如果你是 JFinal 或者纯 Java 用户,这个插件将为你带来 Spring 项目同款缓存体验,却无需引入任何 Spring 依赖!

💬 最后说一句

“JetCache 很强但有点复杂,JFinal(纯 Java)也可以一行接入。”

JetCachePlugin —— 不是重复造轮子,而是把顶级轮子装到 JFinal 的车上。

一行代码,高频访问不崩,缓存击穿无忧,从此告别手写缓存胶水代码!

立即集成,让 JFinal 也能享受 JetCache 的全部威力! 💪

评论区

杜福忠

2025-12-18 20:07

如果是专为JFinal打造的话,建议再加一个类:
public class JetCacheDb implements ICache {...
实现接口,并转调一下JetCacheKit即可

使用:
ActiveRecordPlugin arp = new ActiveRecordPlugin(...);
arp.setCache(new JetCacheDb());

效果:
List list = Db.findByCache(cacheName, key, sql);

这样才是“一行接入 arp.setCache(new JetCacheDb())”

热门分享

扫码入社