From d61c24acece0864abf5f84ec6c24623cc072e641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=8E=E7=94=9FBug=E9=A5=B2=E5=85=BB=E5=91=98?= Date: Sun, 28 Sep 2025 16:57:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?perf(PluginsContextHolder):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=8F=92=E4=BB=B6=E5=88=97=E8=A1=A8=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=80=A7=E8=83=BD=EF=BC=8C=E4=BD=BF=E7=94=A8=E5=B9=B6=E8=A1=8C?= =?UTF-8?q?=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将单次获取10000条插件列表改为分页并行请求,每次获取20条,共500页 使用线程池和CompletableFuture实现并行请求,提高获取速度 汇总所有分页结果后返回完整列表 --- .../help/context/PluginsContextHolder.java | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java b/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java index ffc358f..ba83059 100644 --- a/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java +++ b/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java @@ -26,7 +26,7 @@ public class PluginsContextHolder { private static final String PLUGIN_BASIC_URL = "https://plugins.jetbrains.com"; - private static final String PLUGIN_LIST_URL = PLUGIN_BASIC_URL + "/api/searchPlugins?max=10000&offset=0&orderBy=name"; + private static final String PLUGIN_LIST_URL = PLUGIN_BASIC_URL + "/api/searchPlugins?max=20&orderBy=name"; private static final String PLUGIN_INFO_URL = PLUGIN_BASIC_URL + "/api/plugins/"; @@ -88,19 +88,55 @@ public class PluginsContextHolder { } public static PluginList pluginList() { - return HttpUtil.createGet(PLUGIN_LIST_URL) - .thenFunction(response -> { - try (InputStream is = response.bodyStream()) { - if (!response.isOk()) { - throw new IllegalArgumentException(CharSequenceUtil.format("{} 请求失败! = {}", PLUGIN_LIST_URL, response)); - } - PluginList pluginList = JSONUtil.toBean(IoUtil.readUtf8(is), PluginList.class); - log.info("获取大小 => [{}]", pluginList.getTotal()); - return pluginList; - } catch (IOException e) { - throw new IllegalArgumentException(CharSequenceUtil.format("{} 请求IO读取失败!", PLUGIN_LIST_URL), e); + // 初始化一个空的 PluginList 用于汇总结果 + PluginList resultPluginList = new PluginList(); + resultPluginList.setPlugins(new ArrayList<>()); + resultPluginList.setTotal(0L); + + // 配置线程池,核心线程数 + java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(3); + // 创建一个线程池,使用并行流处理请求 + List> futures = new ArrayList<>(); + for (int i = 0; i < 500; i++) { + int offset = i; + String url = PLUGIN_LIST_URL + "&offset=" + offset; + CompletableFuture future = CompletableFuture.supplyAsync(() -> { + try (InputStream is = HttpUtil.createGet(url).execute().bodyStream()) { + cn.hutool.http.HttpResponse response = HttpUtil.createGet(url).execute(); + if (!response.isOk()) { + throw new IllegalArgumentException(CharSequenceUtil.format("{} 请求失败! = {}", url, response)); } - }); + PluginList currentPluginList = JSONUtil.toBean(IoUtil.readUtf8(is), PluginList.class); + log.info("获取大小 => [{}], 当前第 => [{}] 页", + currentPluginList.getPlugins() != null ? currentPluginList.getPlugins().size() : 0, offset); + return currentPluginList; + } catch (IOException e) { + throw new IllegalArgumentException(CharSequenceUtil.format("{} 请求IO读取失败!", url), e); + } + }, executor); + futures.add(future); + } + + // 等待所有请求完成 + CompletableFuture allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + CompletableFuture> allResults = allFutures.thenApply(v -> + futures.stream() + .map(CompletableFuture::join) + .toList() + ); + + // 汇总结果 + allResults.join().forEach(currentPluginList -> { + if (currentPluginList.getPlugins() != null) { + resultPluginList.getPlugins().addAll(currentPluginList.getPlugins()); + resultPluginList.setTotal(resultPluginList.getTotal() + currentPluginList.getPlugins().size()); + } + }); + + // 关闭线程池 + executor.shutdown(); + + return resultPluginList; } public static List pluginListFilter(PluginList pluginList) { From 7f0091932460ea527017e71c8ecf7201f2846d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=8E=E7=94=9FBug=E9=A5=B2=E5=85=BB=E5=91=98?= Date: Mon, 29 Sep 2025 09:16:31 +0800 Subject: [PATCH 2/2] =?UTF-8?q?refactor(PluginsContextHolder):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=8F=92=E4=BB=B6=E5=88=97=E8=A1=A8=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=80=BB=E9=A1=B5?= =?UTF-8?q?=E6=95=B0=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加分页大小常量PAGE_SIZE,重构插件列表请求逻辑以动态计算总页数 新增getPluginTotleSize方法获取插件总数并计算所需页数 移除硬编码的500页限制,改为根据实际总数计算 --- .../help/context/PluginsContextHolder.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java b/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java index ba83059..ff64d7e 100644 --- a/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java +++ b/src/main/java/com/jetbrains/help/context/PluginsContextHolder.java @@ -6,6 +6,7 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSON; import cn.hutool.json.JSONUtil; import com.jetbrains.help.util.FileTools; import lombok.AccessLevel; @@ -19,14 +20,16 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicInteger; @Slf4j(topic = "插件上下文") @NoArgsConstructor(access = AccessLevel.PRIVATE) public class PluginsContextHolder { + private static final int PAGE_SIZE = 20; private static final String PLUGIN_BASIC_URL = "https://plugins.jetbrains.com"; - private static final String PLUGIN_LIST_URL = PLUGIN_BASIC_URL + "/api/searchPlugins?max=20&orderBy=name"; + private static final String PLUGIN_LIST_URL = PLUGIN_BASIC_URL + "/api/searchPlugins?max="+PAGE_SIZE+"&orderBy=name"; private static final String PLUGIN_INFO_URL = PLUGIN_BASIC_URL + "/api/plugins/"; @@ -92,12 +95,12 @@ public class PluginsContextHolder { PluginList resultPluginList = new PluginList(); resultPluginList.setPlugins(new ArrayList<>()); resultPluginList.setTotal(0L); - + int pluginPageSize = getPluginTotleSize(resultPluginList); // 配置线程池,核心线程数 java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(3); // 创建一个线程池,使用并行流处理请求 List> futures = new ArrayList<>(); - for (int i = 0; i < 500; i++) { + for (int i = 1; i < pluginPageSize; i++) { int offset = i; String url = PLUGIN_LIST_URL + "&offset=" + offset; CompletableFuture future = CompletableFuture.supplyAsync(() -> { @@ -184,6 +187,31 @@ public class PluginsContextHolder { }); } + public static int getPluginTotleSize(PluginList resultPluginList) { + return HttpUtil.createGet(PLUGIN_LIST_URL + "&offset=0") + .thenFunction(response -> { + try (InputStream is = response.bodyStream()) { + if (!response.isOk()) { + throw new IllegalArgumentException(CharSequenceUtil.format("{} 请求失败! = {}", PLUGIN_LIST_URL, response)); + } + String readUtf8 = IoUtil.readUtf8(is); + PluginList currentPluginList = JSONUtil.toBean(readUtf8, PluginList.class); + resultPluginList.getPlugins().addAll(currentPluginList.getPlugins()); + resultPluginList.setTotal(resultPluginList.getTotal() + currentPluginList.getPlugins().size()); + JSON parse = JSONUtil.parse(readUtf8); + int pluginstotal = (int) parse.getByPath("total"); + int total = pluginstotal / PAGE_SIZE; + if (pluginstotal % PAGE_SIZE > 0) { + total = total + 1; + } + return total; + } catch (IOException e) { + log.error(CharSequenceUtil.format("{} 请求IO读取失败!", PLUGIN_LIST_URL + "&offset=0"), e); + return 500; + } + }); + } + @Data public static class PluginCache {