From d9239a2b6829e3f47330aef662e704abd87c2b44 Mon Sep 17 00:00:00 2001 From: zk Date: Wed, 5 Aug 2026 12:34:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=83=AD=E7=82=B9=E7=BC=93?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jiayunet/service/JobService.java | 5 ++ common/pom.xml | 9 +++ .../java/org/jiayunet/config/CacheConfig.java | 69 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 common/src/main/java/org/jiayunet/config/CacheConfig.java diff --git a/client-api/src/main/java/org/jiayunet/service/JobService.java b/client-api/src/main/java/org/jiayunet/service/JobService.java index 12b80e1..955d7b1 100644 --- a/client-api/src/main/java/org/jiayunet/service/JobService.java +++ b/client-api/src/main/java/org/jiayunet/service/JobService.java @@ -2,6 +2,8 @@ package org.jiayunet.service; import org.jiayunet.ai.AiChatAbility; import org.jiayunet.ai.AiResponseCleanTool; +import org.jiayunet.config.CacheConfig; +import org.springframework.cache.annotation.Cacheable; import org.springframework.util.StopWatch; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -212,6 +214,7 @@ public class JobService { *

岗位关联公司、公司关联行业(bg_industry level=2),按上架岗位数量倒序取前 limit 个

*

只返回行业ID和名称,岗位数量仅用于排序不对外暴露

*/ + @Cacheable(cacheNames = CacheConfig.HOT_INDUSTRY) public List listHotIndustries(Integer limit) { return jobMapper.selectHotIndustries(limit); } @@ -221,6 +224,7 @@ public class JobService { *

bg_job.category_id 存三级叶子,SQL 内自关联上溯到二级后按二级分组,按上架岗位数量倒序取前 limit 个

*

只返回岗位类型ID和名称,岗位数量仅用于排序不对外暴露

*/ + @Cacheable(cacheNames = CacheConfig.HOT_JOB_CATEGORY) public List listHotJobCategories(Integer limit) { return jobMapper.selectHotJobCategories(limit); } @@ -230,6 +234,7 @@ public class JobService { *

岗位关联公司、公司关联地区,按上架岗位数量倒序取前 limit 个

*

只返回地区编码和名称,岗位数量仅用于排序不对外暴露

*/ + @Cacheable(cacheNames = CacheConfig.HOT_CITY) public List listHotCities(Integer limit) { return jobMapper.selectHotCities(limit); } diff --git a/common/pom.xml b/common/pom.xml index e4d1821..d52ecc1 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -45,6 +45,15 @@ org.springframework.boot spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-cache + + + com.github.ben-manes.caffeine + caffeine + org.redisson redisson-spring-boot-starter diff --git a/common/src/main/java/org/jiayunet/config/CacheConfig.java b/common/src/main/java/org/jiayunet/config/CacheConfig.java new file mode 100644 index 0000000..bf2e847 --- /dev/null +++ b/common/src/main/java/org/jiayunet/config/CacheConfig.java @@ -0,0 +1,69 @@ +package org.jiayunet.config; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +/** + * 本地缓存配置 + *

基于 Caffeine 的 Spring Cache 实现,用于热门榜单等全局只读、变化慢、允许短时陈旧的数据

+ *

每个缓存独立注册、独立过期时间,调整某个缓存的时长直接改注册时传入的分钟数,互不影响

+ * + * @author zk + */ +@Configuration +@EnableCaching +public class CacheConfig { + + /** 缓存名:热门行业 */ + public static final String HOT_INDUSTRY = "hotIndustry"; + + /** 缓存名:热门岗位类型 */ + public static final String HOT_JOB_CATEGORY = "hotJobCategory"; + + /** 缓存名:热门城市 */ + public static final String HOT_CITY = "hotCity"; + + /** 单个缓存最大条目数 */ + private static final long MAX_SIZE = 100; + + /** + * 缓存管理器 + *

三个热门榜单各注册一份独立的 Caffeine 实例,过期时间互相独立(单位:分钟)

+ *

另设一份兜底策略:业务里如果用了未登记的缓存名,动态创建时同样带过期时间,不会永不过期

+ */ + @Bean + public CacheManager cacheManager() { + CaffeineCacheManager cacheManager = new CaffeineCacheManager(); + + // 兜底策略(动态创建未登记缓存时生效) + cacheManager.setCaffeine(Caffeine.newBuilder() + .expireAfterWrite(30, TimeUnit.MINUTES) + .maximumSize(MAX_SIZE)); + + // 各缓存独立注册,独立过期时间 + cacheManager.registerCustomCache(HOT_INDUSTRY, buildCache(60)); + cacheManager.registerCustomCache(HOT_JOB_CATEGORY, buildCache(60)); + cacheManager.registerCustomCache(HOT_CITY, buildCache(60)); + + return cacheManager; + } + + /** + * 构建一个指定过期时长的 Caffeine 缓存实例 + * + * @param expireMinutes 写入后过期时长(分钟) + */ + private Cache buildCache(long expireMinutes) { + return Caffeine.newBuilder() + .expireAfterWrite(expireMinutes, TimeUnit.MINUTES) + .maximumSize(MAX_SIZE) + .build(); + } +}