mirror of
https://github.com/zfile-dev/zfile.git
synced 2025-04-19 05:34:52 +00:00
✨ 新增缓存管理功能, 支持手动/自动刷新缓存, 查看、清理缓存。
This commit is contained in:
19
src/main/java/im/zhaojun/zfile/cache/DriveCacheKey.java
vendored
Normal file
19
src/main/java/im/zhaojun/zfile/cache/DriveCacheKey.java
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
package im.zhaojun.zfile.cache;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DriveCacheKey {
|
||||
|
||||
private Integer driveId;
|
||||
|
||||
private String key;
|
||||
|
||||
}
|
||||
43
src/main/java/im/zhaojun/zfile/cache/MyTimedCache.java
vendored
Normal file
43
src/main/java/im/zhaojun/zfile/cache/MyTimedCache.java
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package im.zhaojun.zfile.cache;
|
||||
|
||||
import cn.hutool.cache.impl.CacheObj;
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.util.SpringContextHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Slf4j
|
||||
public class MyTimedCache<K, V> extends TimedCache<K, V> {
|
||||
|
||||
private DriveContext driveContext;
|
||||
|
||||
public MyTimedCache(long timeout) {
|
||||
super(timeout);
|
||||
}
|
||||
|
||||
public MyTimedCache(long timeout, Map<K, CacheObj<K, V>> map) {
|
||||
super(timeout, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove(K key, V cachedObject) {
|
||||
log.debug("尝试刷新缓存: " + key);
|
||||
if (driveContext == null) {
|
||||
driveContext = SpringContextHolder.getBean(DriveContext.class);
|
||||
}
|
||||
DriveCacheKey cacheKey = (DriveCacheKey) key;
|
||||
AbstractBaseFileService baseFileService = driveContext.getDriveService(cacheKey.getDriveId());
|
||||
try {
|
||||
baseFileService.fileList(cacheKey.getKey());
|
||||
} catch (Exception e) {
|
||||
log.error("尝试刷新驱动器 {} 的 {} 失败, ", cacheKey.getDriveId(), cacheKey.getKey());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package im.zhaojun.zfile.cache;
|
||||
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import cn.hutool.cache.impl.CacheObj;
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import im.zhaojun.zfile.model.constant.ZFileConstant;
|
||||
import im.zhaojun.zfile.model.dto.FileItemDTO;
|
||||
@@ -33,6 +31,9 @@ public class ZFileCache {
|
||||
@Value("${zfile.cache.timeout}")
|
||||
private long timeout;
|
||||
|
||||
@Value("${zfile.cache.auto-refresh.interval}")
|
||||
private long autoRefreshInterval;
|
||||
|
||||
|
||||
/**
|
||||
* 缓存 map 对象.
|
||||
@@ -44,7 +45,7 @@ public class ZFileCache {
|
||||
* key: 文件夹路径
|
||||
* value: 文件夹中内容
|
||||
*/
|
||||
private ConcurrentMap<Integer, TimedCache<String, List<FileItemDTO>>> drivesCache = new ConcurrentHashMap<>();
|
||||
private ConcurrentMap<Integer, MyTimedCache<DriveCacheKey, List<FileItemDTO>>> drivesCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 系统设置缓存
|
||||
@@ -68,7 +69,7 @@ public class ZFileCache {
|
||||
* 文件夹中列表
|
||||
*/
|
||||
public synchronized void put(Integer driveId, String key, List<FileItemDTO> value) {
|
||||
getCacheByDriveId(driveId).put(key, value);
|
||||
getCacheByDriveId(driveId).put(new DriveCacheKey(driveId, key), value);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +85,7 @@ public class ZFileCache {
|
||||
* @return 驱动器中文件夹的内容
|
||||
*/
|
||||
public List<FileItemDTO> get(Integer driveId, String key) {
|
||||
return getCacheByDriveId(driveId).get(key, false);
|
||||
return getCacheByDriveId(driveId).get(new DriveCacheKey(driveId, key), false);
|
||||
}
|
||||
|
||||
|
||||
@@ -161,10 +162,10 @@ public class ZFileCache {
|
||||
* @return 所有缓存 key
|
||||
*/
|
||||
public Set<String> keySet(Integer driveId) {
|
||||
Iterator<CacheObj<String, List<FileItemDTO>>> cacheObjIterator = getCacheByDriveId(driveId).cacheObjIterator();
|
||||
Iterator<CacheObj<DriveCacheKey, List<FileItemDTO>>> cacheObjIterator = getCacheByDriveId(driveId).cacheObjIterator();
|
||||
Set<String> keys = new HashSet<>();
|
||||
while (cacheObjIterator.hasNext()) {
|
||||
keys.add(cacheObjIterator.next().getKey());
|
||||
keys.add(cacheObjIterator.next().getKey().getKey());
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
@@ -180,7 +181,7 @@ public class ZFileCache {
|
||||
* 文件夹路径
|
||||
*/
|
||||
public void remove(Integer driveId, String key) {
|
||||
getCacheByDriveId(driveId).remove(key);
|
||||
getCacheByDriveId(driveId).remove(new DriveCacheKey(driveId, key));
|
||||
}
|
||||
|
||||
|
||||
@@ -241,14 +242,74 @@ public class ZFileCache {
|
||||
*
|
||||
* @return 驱动器对应的缓存
|
||||
*/
|
||||
private synchronized TimedCache<String, List<FileItemDTO>> getCacheByDriveId(Integer driveId) {
|
||||
TimedCache<String, List<FileItemDTO>> driveCache = drivesCache.get(driveId);
|
||||
private synchronized MyTimedCache<DriveCacheKey, List<FileItemDTO>> getCacheByDriveId(Integer driveId) {
|
||||
MyTimedCache<DriveCacheKey, List<FileItemDTO>> driveCache = drivesCache.get(driveId);
|
||||
if (driveCache == null) {
|
||||
driveCache = CacheUtil.newTimedCache(timeout * 1000);
|
||||
driveCache = new MyTimedCache<>(timeout * 1000);
|
||||
drivesCache.put(driveId, driveCache);
|
||||
startAutoCacheRefresh(driveId);
|
||||
}
|
||||
|
||||
return driveCache;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器的缓存命中数
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 缓存命中数
|
||||
*/
|
||||
public int getHitCount(Integer driveId) {
|
||||
return getCacheByDriveId(driveId).getHitCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器的缓存未命中数
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @return 缓存未命中数
|
||||
*/
|
||||
public int getMissCount(Integer driveId) {
|
||||
return getCacheByDriveId(driveId).getMissCount();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开启缓存自动刷新, 仅当数据库设置为开启时, 才会真正开启缓存自动刷新.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public void startAutoCacheRefresh(Integer driveId) {
|
||||
DriveConfig driveConfig = driverConfigRepository.findById(driveId).get();
|
||||
Boolean autoRefreshCache = driveConfig.getAutoRefreshCache();
|
||||
if (autoRefreshCache != null && autoRefreshCache) {
|
||||
MyTimedCache<DriveCacheKey, List<FileItemDTO>> driveCache = drivesCache.get(driveId);
|
||||
if (driveCache == null) {
|
||||
driveCache = new MyTimedCache<>(timeout * 1000);
|
||||
drivesCache.put(driveId, driveCache);
|
||||
}
|
||||
driveCache.schedulePrune(autoRefreshInterval * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止缓存自动刷新
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public void stopAutoCacheRefresh(Integer driveId) {
|
||||
MyTimedCache<DriveCacheKey, List<FileItemDTO>> driveCache = drivesCache.get(driveId);
|
||||
if (driveCache != null) {
|
||||
driveCache.cancelPruneSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package im.zhaojun.zfile.controller.admin;
|
||||
|
||||
import im.zhaojun.zfile.model.dto.CacheInfoDTO;
|
||||
import im.zhaojun.zfile.model.dto.ResultBean;
|
||||
import im.zhaojun.zfile.service.DriveConfigService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -21,17 +23,50 @@ public class CacheController {
|
||||
@Resource
|
||||
private DriveConfigService driveConfigService;
|
||||
|
||||
|
||||
@PostMapping("/{driveId}/enable")
|
||||
public ResultBean enableCache(@PathVariable("driveId") Integer driveId) {
|
||||
driveConfigService.updateCacheStatus(driveId, true);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{driveId}/disable")
|
||||
public ResultBean disableCache(@PathVariable("driveId") Integer driveId) {
|
||||
driveConfigService.updateCacheStatus(driveId, false);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/{driveId}/info")
|
||||
public ResultBean cacheInfo(@PathVariable("driveId") Integer driveId) {
|
||||
CacheInfoDTO cacheInfo = driveConfigService.findCacheInfo(driveId);
|
||||
return ResultBean.success(cacheInfo);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{driveId}/refresh")
|
||||
public ResultBean refreshCache(@PathVariable("driveId") Integer driveId, String key) throws Exception {
|
||||
driveConfigService.refreshCache(driveId, key);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
@PostMapping("/{driveId}/auto-refresh/start")
|
||||
public ResultBean enableAutoRefresh(@PathVariable("driveId") Integer driveId) {
|
||||
driveConfigService.startAutoCacheRefresh(driveId);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{driveId}/auto-refresh/stop")
|
||||
public ResultBean disableAutoRefresh(@PathVariable("driveId") Integer driveId) {
|
||||
driveConfigService.stopAutoCacheRefresh(driveId);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
@PostMapping("/{driveId}/clear")
|
||||
public ResultBean clearCache(@PathVariable("driveId") Integer driveId) {
|
||||
driveConfigService.clearCache(driveId);
|
||||
return ResultBean.success();
|
||||
}
|
||||
|
||||
}
|
||||
23
src/main/java/im/zhaojun/zfile/model/dto/CacheInfoDTO.java
Normal file
23
src/main/java/im/zhaojun/zfile/model/dto/CacheInfoDTO.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package im.zhaojun.zfile.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author zhaojun
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class CacheInfoDTO {
|
||||
|
||||
private Integer cacheCount;
|
||||
|
||||
private Integer hitCount;
|
||||
|
||||
private Integer missCount;
|
||||
|
||||
private Set<String> cacheKeys;
|
||||
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package im.zhaojun.zfile.service;
|
||||
|
||||
import im.zhaojun.zfile.cache.ZFileCache;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import im.zhaojun.zfile.context.StorageTypeContext;
|
||||
import im.zhaojun.zfile.exception.InitializeException;
|
||||
import im.zhaojun.zfile.model.constant.StorageConfigConstant;
|
||||
import im.zhaojun.zfile.model.dto.CacheInfoDTO;
|
||||
import im.zhaojun.zfile.model.dto.DriveConfigDTO;
|
||||
import im.zhaojun.zfile.model.dto.StorageStrategyConfig;
|
||||
import im.zhaojun.zfile.model.entity.DriveConfig;
|
||||
@@ -11,7 +14,6 @@ import im.zhaojun.zfile.model.enums.StorageTypeEnum;
|
||||
import im.zhaojun.zfile.repository.DriverConfigRepository;
|
||||
import im.zhaojun.zfile.repository.StorageConfigRepository;
|
||||
import im.zhaojun.zfile.service.base.AbstractBaseFileService;
|
||||
import im.zhaojun.zfile.context.DriveContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -21,6 +23,7 @@ import javax.annotation.Resource;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 驱动器 Service 类
|
||||
@@ -39,6 +42,9 @@ public class DriveConfigService {
|
||||
@Resource
|
||||
private DriveContext driveContext;
|
||||
|
||||
@Resource
|
||||
private ZFileCache zFileCache;
|
||||
|
||||
public static final Class<StorageStrategyConfig> STORAGE_STRATEGY_CONFIG_CLASS = StorageStrategyConfig.class;
|
||||
|
||||
/**
|
||||
@@ -60,7 +66,7 @@ public class DriveConfigService {
|
||||
* @return 驱动器设置
|
||||
*/
|
||||
public DriveConfig findById(Integer id) {
|
||||
return driverConfigRepository.getOne(id);
|
||||
return driverConfigRepository.findById(id).get();
|
||||
}
|
||||
|
||||
|
||||
@@ -137,6 +143,12 @@ public class DriveConfigService {
|
||||
BeanUtils.copyProperties(driveConfigDTO, driveConfig);
|
||||
driverConfigRepository.save(driveConfig);
|
||||
|
||||
if (driveConfig.getAutoRefreshCache()) {
|
||||
startAutoCacheRefresh(driveConfig.getId());
|
||||
} else {
|
||||
stopAutoCacheRefresh(driveConfig.getId());
|
||||
}
|
||||
|
||||
// 保存存储策略设置.
|
||||
StorageStrategyConfig storageStrategyConfig = driveConfigDTO.getStorageStrategyConfig();
|
||||
|
||||
@@ -221,4 +233,97 @@ public class DriveConfigService {
|
||||
driverConfigRepository.save(driveConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新指定驱动器的缓存启用状态
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param autoRefreshCache
|
||||
* 是否启用缓存自动刷新
|
||||
*/
|
||||
public void updateAutoRefreshCacheStatus(Integer driveId, Boolean autoRefreshCache) {
|
||||
DriveConfig driveConfig = findById(driveId);
|
||||
if (driveConfig != null) {
|
||||
driveConfig.setAutoRefreshCache(autoRefreshCache);
|
||||
driverConfigRepository.save(driveConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取指定驱动器的缓存信息
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
* @return 缓存信息
|
||||
*/
|
||||
public CacheInfoDTO findCacheInfo(Integer driveId) {
|
||||
int hitCount = zFileCache.getHitCount(driveId);
|
||||
int missCount = zFileCache.getMissCount(driveId);
|
||||
Set<String> keys = zFileCache.keySet(driveId);
|
||||
int cacheCount = keys.size();
|
||||
return new CacheInfoDTO(cacheCount, hitCount, missCount, keys);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 刷新指定 key 的缓存:
|
||||
* 1. 清空此 key 的缓存.
|
||||
* 2. 重新调用方法写入缓存.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*
|
||||
* @param key
|
||||
* 缓存 key (文件夹名称)
|
||||
*/
|
||||
public void refreshCache(Integer driveId, String key) throws Exception {
|
||||
zFileCache.remove(driveId, key);
|
||||
AbstractBaseFileService baseFileService = driveContext.getDriveService(driveId);
|
||||
baseFileService.fileList(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 开启缓存自动刷新, 仅当数据库设置为开启时, 才会真正开启缓存自动刷新.
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public void startAutoCacheRefresh(Integer driveId) {
|
||||
DriveConfig driveConfig = findById(driveId);
|
||||
driveConfig.setAutoRefreshCache(true);
|
||||
driverConfigRepository.save(driveConfig);
|
||||
zFileCache.startAutoCacheRefresh(driveId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止缓存自动刷新
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public void stopAutoCacheRefresh(Integer driveId) {
|
||||
DriveConfig driveConfig = findById(driveId);
|
||||
driveConfig.setAutoRefreshCache(false);
|
||||
driverConfigRepository.save(driveConfig);
|
||||
zFileCache.stopAutoCacheRefresh(driveId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*
|
||||
* @param driveId
|
||||
* 驱动器 ID
|
||||
*/
|
||||
public void clearCache(Integer driveId) {
|
||||
zFileCache.clear(driveId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -140,21 +140,6 @@ public abstract class AbstractBaseFileService implements BaseFileService {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新指定 key 的缓存:
|
||||
* 1. 清空此 key 的缓存.
|
||||
* 2. 重新调用方法写入缓存.
|
||||
*
|
||||
* @param key
|
||||
* 缓存 key (文件夹名称)
|
||||
*/
|
||||
public void refreshCache(String key) throws Exception {
|
||||
zFileCache.remove(driveId, key);
|
||||
BaseFileService currentFileService = (BaseFileService) AopContext.currentProxy();
|
||||
currentFileService.fileList(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取单个文件信息
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user