diff --git a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleController.java b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleController.java index bca6397..11e52df 100644 --- a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleController.java +++ b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleController.java @@ -289,13 +289,19 @@ public class ArticleController { /** * 创建文章的临时访问缓存 * - * @param id 文章ID + * @param id 文章ID + * @param duration 临时访问的过期时间 * @return 临时访问Key * @since 1.9.0 */ @GetMapping("/temp/key") - public R createTempVisitKey(@RequestParam("id") Long id) { - return R.ok(tempVisitService.create(id, AuthContext.getUserId())); + public R createTempVisitKey(@RequestParam("id") Long id, + @RequestParam(value = "duration", required = false) Long duration) { + if (duration == null) { + duration = 3 * 60L; + } + log.info("创建文章临时访问权限 [{}:{}m]", id, duration); + return R.ok(tempVisitService.create(id, AuthContext.getUserId(), duration)); } /** diff --git a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleTempVisitService.java b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleTempVisitService.java index 8140a8e..c3a9f64 100644 --- a/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleTempVisitService.java +++ b/blossom-backend/backend/src/main/java/com/blossom/backend/server/article/draft/ArticleTempVisitService.java @@ -3,6 +3,7 @@ package com.blossom.backend.server.article.draft; import cn.hutool.core.util.ObjUtil; import com.blossom.common.base.exception.XzException400; import com.blossom.common.base.util.security.SHA256Util; +import com.blossom.common.cache.caffeine.DynamicExpiry; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.RemovalCause; @@ -10,6 +11,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -24,25 +26,31 @@ public class ArticleTempVisitService { /** * 存放文章ID的缓存 + * + * @since 1.13.0 支持动态过期时间 */ private final Cache tempVisitCache = Caffeine.newBuilder() + .expireAfter(new DynamicExpiry()) .initialCapacity(500) - .expireAfterWrite(3, TimeUnit.HOURS) .removalListener((String key, TempVisit value, RemovalCause cause) -> - log.info("临时访问文章 [" + value.getArticleId() + "] 被删除") + log.info("remove temp visit articleId [" + Objects.requireNonNull(value).getArticleId() + "]") ) .build(); /** - * 生成一个缓存 key, key 并非文章的摘要码 + * 生成一个缓存 key, key 并非文章的摘要码, * * @param articleId 文章ID + * @param userId 用户ID + * @param duration 过期时间, 单位分钟 * @return 缓存 key */ - public String create(Long articleId, Long userId) { + public String create(Long articleId, Long userId, Long duration) { XzException400.throwBy(ObjUtil.isNull(articleId), "文章ID为必填项"); String key = SHA256Util.encode(UUID.randomUUID().toString()); - tempVisitCache.put(key, new TempVisit(articleId, userId)); + tempVisitCache.policy().expireVariably().ifPresent(e -> { + e.put(key, new TempVisit(articleId, userId), duration, TimeUnit.MINUTES); + }); return key; } diff --git a/blossom-backend/common/common-cache/src/main/java/com/blossom/common/cache/caffeine/DynamicExpiry.java b/blossom-backend/common/common-cache/src/main/java/com/blossom/common/cache/caffeine/DynamicExpiry.java new file mode 100644 index 0000000..ff8997d --- /dev/null +++ b/blossom-backend/common/common-cache/src/main/java/com/blossom/common/cache/caffeine/DynamicExpiry.java @@ -0,0 +1,28 @@ +package com.blossom.common.cache.caffeine; + +import com.github.benmanes.caffeine.cache.Expiry; +import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * key 使用不同的过期时间 + * + * @since 1.13.0 + */ +public class DynamicExpiry implements Expiry { + + @Override + public long expireAfterCreate(@NonNull String key, @NonNull Object value, long currentTime) { + return 0; + } + + @Override + public long expireAfterUpdate(@NonNull String key, @NonNull Object value, long currentTime, @NonNegative long currentDuration) { + return currentDuration; + } + + @Override + public long expireAfterRead(@NonNull String key, @NonNull Object value, long currentTime, @NonNegative long currentDuration) { + return currentDuration; + } +} diff --git a/blossom-backend/common/common-base/src/main/java/com/blossom/common/base/caffeine/Test.java b/blossom-backend/common/common-cache/src/main/java/com/blossom/common/cache/caffeine/Test.java similarity index 61% rename from blossom-backend/common/common-base/src/main/java/com/blossom/common/base/caffeine/Test.java rename to blossom-backend/common/common-cache/src/main/java/com/blossom/common/cache/caffeine/Test.java index dce3a73..ac22b56 100644 --- a/blossom-backend/common/common-base/src/main/java/com/blossom/common/base/caffeine/Test.java +++ b/blossom-backend/common/common-cache/src/main/java/com/blossom/common/cache/caffeine/Test.java @@ -1,4 +1,4 @@ -package com.blossom.common.base.caffeine; +package com.blossom.common.cache.caffeine; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; @@ -13,25 +13,31 @@ import java.util.concurrent.TimeUnit; public class Test { private static final Cache cache = Caffeine.newBuilder() + .expireAfter(new DynamicExpiry()) .initialCapacity(100) - .expireAfterWrite(10, TimeUnit.SECONDS) - .removalListener((String key, String value, RemovalCause cause) -> System.out.println(key + " 被删除")) + .removalListener((String key, String value, RemovalCause cause) -> log.info(key + " 被删除")) .build(); + private static final ScheduledExecutorService clearUpScheduled = Executors.newScheduledThreadPool(1); public Test() { - clearUpScheduled.scheduleWithFixedDelay(this::clear, 5, 1, TimeUnit.SECONDS); + clearUpScheduled.scheduleWithFixedDelay(this::clear, 0, 1, TimeUnit.SECONDS); } private void clear() { - log.info("尝试过期缓存"); + log.info("删除"); cache.cleanUp(); } - public static void main(String[] args) { - Test test = new Test(); + public static void main(String[] args) throws InterruptedException { + Test t = new Test(); cache.policy().expireVariably().ifPresent(e -> { + e.put("A1", "1", 7, TimeUnit.SECONDS); }); + cache.policy().expireVariably().ifPresent(e -> { + e.put("A2", "2", 3, TimeUnit.SECONDS); + }); + Thread.sleep(20 * 1000); } } diff --git a/blossom-editor/src/renderer/src/assets/styles/bl-tooltip.scss b/blossom-editor/src/renderer/src/assets/styles/bl-tooltip.scss index fad6b73..efa39db 100644 --- a/blossom-editor/src/renderer/src/assets/styles/bl-tooltip.scss +++ b/blossom-editor/src/renderer/src/assets/styles/bl-tooltip.scss @@ -120,4 +120,5 @@ .el-popper.is-small { padding: 0 8px; + box-shadow: 1px 1px 3px #f4f4f4; } diff --git a/blossom-editor/src/renderer/src/views/article/ArticleCustomTempVisit.vue b/blossom-editor/src/renderer/src/views/article/ArticleCustomTempVisit.vue new file mode 100644 index 0000000..4c1b176 --- /dev/null +++ b/blossom-editor/src/renderer/src/views/article/ArticleCustomTempVisit.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/blossom-editor/src/renderer/src/views/article/ArticleTreeDocs.vue b/blossom-editor/src/renderer/src/views/article/ArticleTreeDocs.vue index cddd4f1..b60c517 100644 --- a/blossom-editor/src/renderer/src/views/article/ArticleTreeDocs.vue +++ b/blossom-editor/src/renderer/src/views/article/ArticleTreeDocs.vue @@ -99,7 +99,6 @@
暂无文档,可点击上方 ↑ 添加
-
重命名
编辑详情
同步文章
-
新增文件夹
新增笔记
复制双链引用
导入文章
-
更多 @@ -146,7 +143,6 @@
新窗口查看
浏览器临时访问
-
导出文章 @@ -159,10 +155,11 @@
- 复制链接 + 创建链接
博客中查看
@@ -224,6 +221,18 @@ :close-on-click-modal="true"> + + + + +