feat(缓存): 添加Caffeine缓存管理接口及功能扩展
- 新增CaffeineController提供缓存查询、统计和清空功能 - 在AbstractCaffeineCacheTemplate中添加getAll和getAllWithOptional方法 - 更新.claude配置添加mvnw相关命令
This commit is contained in:
parent
a78da5cb59
commit
e41c7c27f5
|
|
@ -36,7 +36,8 @@
|
||||||
"Bash(cat \"/e/code/智柜宝/shop-back-end/agileboot-domain/src/main/java/com/agileboot/domain/system/user/query/SearchUserQuery.java\")",
|
"Bash(cat \"/e/code/智柜宝/shop-back-end/agileboot-domain/src/main/java/com/agileboot/domain/system/user/query/SearchUserQuery.java\")",
|
||||||
"Bash(./mvnw clean compile -pl agileboot-api -am -DskipTests)",
|
"Bash(./mvnw clean compile -pl agileboot-api -am -DskipTests)",
|
||||||
"Bash(./mvnw clean compile -pl agileboot-api,agileboot-domain -am -DskipTests)",
|
"Bash(./mvnw clean compile -pl agileboot-api,agileboot-domain -am -DskipTests)",
|
||||||
"Bash(./mvnw clean compile -pl agileboot-domain -am -DskipTests)"
|
"Bash(./mvnw clean compile -pl agileboot-domain -am -DskipTests)",
|
||||||
|
"Bash(./mvnw:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
package com.agileboot.api.controller;
|
||||||
|
|
||||||
|
import com.agileboot.domain.common.cache.CaffeineCacheService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caffeine缓存管理控制器
|
||||||
|
* 提供缓存查询、统计、清空等管理功能
|
||||||
|
*
|
||||||
|
* @author valarchie
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/caffeine")
|
||||||
|
@Tag(name = "Caffeine缓存管理", description = "Caffeine本地缓存查询和管理接口")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CaffeineController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CaffeineCacheService caffeineCacheService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有Caffeine缓存的统计信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/stats")
|
||||||
|
@Operation(summary = "获取缓存统计信息", description = "返回所有Caffeine缓存的详细统计信息")
|
||||||
|
public ResponseEntity<String> getCacheStats() {
|
||||||
|
try {
|
||||||
|
String stats = caffeineCacheService.getCacheStats();
|
||||||
|
return ResponseEntity.ok(stats);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取缓存统计信息失败", e);
|
||||||
|
return ResponseEntity.internalServerError()
|
||||||
|
.body("获取缓存统计信息失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空指定类型的缓存
|
||||||
|
*
|
||||||
|
* @param cacheName 缓存名称 (captchaCache, loginUserCache, userCache, roleCache, postCache, qyUseridCache, dynamicCodeCache)
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/cache/{cacheName}")
|
||||||
|
@Operation(summary = "清空指定缓存", description = "清空指定类型的Caffeine缓存")
|
||||||
|
public ResponseEntity<String> clearCache(@PathVariable String cacheName) {
|
||||||
|
try {
|
||||||
|
switch (cacheName) {
|
||||||
|
case "captchaCache":
|
||||||
|
caffeineCacheService.captchaCache.invalidateAll();
|
||||||
|
break;
|
||||||
|
case "loginUserCache":
|
||||||
|
caffeineCacheService.loginUserCache.invalidateAll();
|
||||||
|
break;
|
||||||
|
case "userCache":
|
||||||
|
caffeineCacheService.userCache.invalidateAll();
|
||||||
|
break;
|
||||||
|
case "roleCache":
|
||||||
|
caffeineCacheService.roleCache.invalidateAll();
|
||||||
|
break;
|
||||||
|
case "postCache":
|
||||||
|
caffeineCacheService.postCache.invalidateAll();
|
||||||
|
break;
|
||||||
|
case "qyUseridCache":
|
||||||
|
caffeineCacheService.qyUseridCache.invalidateAll();
|
||||||
|
break;
|
||||||
|
case "dynamicCodeCache":
|
||||||
|
caffeineCacheService.dynamicCodeCache.invalidateAll();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body("未知的缓存类型: " + cacheName + ",支持的类型: captchaCache, loginUserCache, userCache, roleCache, postCache, qyUseridCache, dynamicCodeCache");
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok("缓存 [" + cacheName + "] 已清空");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("清空缓存失败: {}", cacheName, e);
|
||||||
|
return ResponseEntity.internalServerError()
|
||||||
|
.body("清空缓存失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空所有Caffeine缓存
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/cache")
|
||||||
|
@Operation(summary = "清空所有缓存", description = "清空所有类型的Caffeine缓存")
|
||||||
|
public ResponseEntity<String> clearAllCaches() {
|
||||||
|
try {
|
||||||
|
caffeineCacheService.captchaCache.invalidateAll();
|
||||||
|
caffeineCacheService.loginUserCache.invalidateAll();
|
||||||
|
caffeineCacheService.userCache.invalidateAll();
|
||||||
|
caffeineCacheService.roleCache.invalidateAll();
|
||||||
|
caffeineCacheService.postCache.invalidateAll();
|
||||||
|
caffeineCacheService.qyUseridCache.invalidateAll();
|
||||||
|
caffeineCacheService.dynamicCodeCache.invalidateAll();
|
||||||
|
|
||||||
|
return ResponseEntity.ok("所有Caffeine缓存已清空");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("清空所有缓存失败", e);
|
||||||
|
return ResponseEntity.internalServerError()
|
||||||
|
.body("清空所有缓存失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有缓存数据
|
||||||
|
*/
|
||||||
|
@GetMapping("/cache/all")
|
||||||
|
@Operation(summary = "获取所有缓存数据", description = "获取所有Caffeine缓存中的数据")
|
||||||
|
public ResponseEntity<?> getAllCacheData() {
|
||||||
|
try {
|
||||||
|
Map<String, Object> allCaches = new HashMap<>();
|
||||||
|
allCaches.put("captchaCache", caffeineCacheService.captchaCache.getAll());
|
||||||
|
allCaches.put("loginUserCache", caffeineCacheService.loginUserCache.getAll());
|
||||||
|
allCaches.put("userCache", caffeineCacheService.userCache.getAll());
|
||||||
|
allCaches.put("roleCache", caffeineCacheService.roleCache.getAll());
|
||||||
|
allCaches.put("postCache", caffeineCacheService.postCache.getAll());
|
||||||
|
allCaches.put("qyUseridCache", caffeineCacheService.qyUseridCache.getAll());
|
||||||
|
allCaches.put("dynamicCodeCache", caffeineCacheService.dynamicCodeCache.getAll());
|
||||||
|
|
||||||
|
return ResponseEntity.ok(allCaches);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取所有缓存数据失败", e);
|
||||||
|
return ResponseEntity.internalServerError()
|
||||||
|
.body("获取所有缓存数据失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定缓存的数据
|
||||||
|
*/
|
||||||
|
@GetMapping("/cache/{cacheName}/data")
|
||||||
|
@Operation(summary = "获取指定缓存数据", description = "获取指定类型的Caffeine缓存数据")
|
||||||
|
public ResponseEntity<?> getCacheData(@PathVariable String cacheName) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("cacheName", cacheName);
|
||||||
|
|
||||||
|
switch (cacheName) {
|
||||||
|
case "captchaCache":
|
||||||
|
result.put("data", caffeineCacheService.captchaCache.getAll());
|
||||||
|
break;
|
||||||
|
case "loginUserCache":
|
||||||
|
result.put("data", caffeineCacheService.loginUserCache.getAll());
|
||||||
|
break;
|
||||||
|
case "userCache":
|
||||||
|
result.put("data", caffeineCacheService.userCache.getAll());
|
||||||
|
break;
|
||||||
|
case "roleCache":
|
||||||
|
result.put("data", caffeineCacheService.roleCache.getAll());
|
||||||
|
break;
|
||||||
|
case "postCache":
|
||||||
|
result.put("data", caffeineCacheService.postCache.getAll());
|
||||||
|
break;
|
||||||
|
case "qyUseridCache":
|
||||||
|
result.put("data", caffeineCacheService.qyUseridCache.getAll());
|
||||||
|
break;
|
||||||
|
case "dynamicCodeCache":
|
||||||
|
result.put("data", caffeineCacheService.dynamicCodeCache.getAll());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(Map.of("error", "未知的缓存类型: " + cacheName,
|
||||||
|
"supportedTypes", new String[]{
|
||||||
|
"captchaCache", "loginUserCache", "userCache",
|
||||||
|
"roleCache", "postCache", "qyUseridCache", "dynamicCodeCache"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取缓存数据失败: {}", cacheName, e);
|
||||||
|
return ResponseEntity.internalServerError()
|
||||||
|
.body(Map.of("error", "获取缓存数据失败: " + e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil;
|
||||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
@ -132,6 +133,37 @@ public abstract class AbstractCaffeineCacheTemplate<T> {
|
||||||
return caffeineCache.stats().toString();
|
return caffeineCache.stats().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存中所有数据
|
||||||
|
* @return 缓存中的所有数据(不包含值为null的条目)
|
||||||
|
*/
|
||||||
|
public java.util.Map<String, T> getAll() {
|
||||||
|
try {
|
||||||
|
return caffeineCache.asMap().entrySet().stream()
|
||||||
|
.filter(entry -> entry.getValue().isPresent())
|
||||||
|
.collect(java.util.stream.Collectors.toMap(
|
||||||
|
Map.Entry::getKey,
|
||||||
|
entry -> entry.getValue().get()
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取Caffeine缓存所有数据失败", e);
|
||||||
|
return new java.util.HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存中所有数据(包括key和value)
|
||||||
|
* @return 包含key和Optional<T>的Map
|
||||||
|
*/
|
||||||
|
public java.util.Map<String, Optional<T>> getAllWithOptional() {
|
||||||
|
try {
|
||||||
|
return new java.util.HashMap<>(caffeineCache.asMap());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取Caffeine缓存所有数据失败", e);
|
||||||
|
return new java.util.HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从数据库加载数据
|
* 从数据库加载数据
|
||||||
* @param id 数据ID
|
* @param id 数据ID
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue