From 1731a3ca60ef88ed081cb194ef05fe81a3300b69 Mon Sep 17 00:00:00 2001 From: wanghanlin <1533525126@qq.com> Date: Thu, 10 Sep 2026 17:29:18 +0800 Subject: [PATCH] =?UTF-8?q?chore(deps):=20=E5=8D=87=E7=BA=A7=20Spring=20Bo?= =?UTF-8?q?ot=203.5.8=20/=20Spring=20AI=201.1.2=20/=20Spring=20AI=20Alibab?= =?UTF-8?q?a=201.1.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 升级到官方兼容矩阵组合(SAA 1.1.2.2 的官方基线即 Boot 3.5.8 + SAI 1.1.2)。 编译适配 - SAA 1.1.2.2 将内部类 DashscopeChatOptionsBuilder 更名为 DashScopeChatOptionsBuilder - Spring AI 1.1.x 起 AssistantMessage/ToolResponseMessage 带 metadata 的构造器改为 protected,MessageConverter 改用标准 builder 依赖增删 - MCP SDK 继续排除传递依赖并锁定 0.18.3:1.1.2 传递的是 0.17.0,其 JsonMapper 包名 为 json.jackson(无 jackson2),与本项目使用的 json.jackson2 不兼容,不锁版本会编译失败; 已核对 spring-ai-mcp 1.1.2 仅引用 McpSyncClient/McpAsyncClient/McpClient/ McpTransportContext/McpSchema/Assert,这些类 0.18.3 均存在,覆盖安全 - 删除 spring-security-oauth2-client:原为 Spring AI 1.0.x ToolCallingAutoConfiguration 的 ClassNotFound workaround,1.1.2 已无该耦合(已核对字节码常量池零 oauth2 引用) - 删除显式 victools jsonschema-generator:改由 spring-ai-model 传递引入(4.38.0), 顺带消除原先 4.38.0/4.37.0 混用 - 删除 kryo:唯一使用者 FileBasedChatMemory 为死代码,本提交一并删除 - 新增 jtokkit 1.1.0(OverlapTokenTextSplitter 直接使用) - 升 Knife4j 4.5.0、MyBatis-Plus 3.5.14、hutool 5.8.41、jjwt 0.12.7; Lombok 版本交由 Boot 父 POM 托管(1.18.42) 刻意不采纳的升级建议 - 不导入 spring-ai-alibaba-bom:该 BOM 的 dependencyManagement 并不包含 spring-ai-alibaba-starter-dashscope,导入后仍需显式写版本号,无收益 - 保留 spring-ai-openai / spring-ai-pgvector-store 的非 starter 坐标:项目手动构建 ChatModel/EmbeddingModel/VectorStore,换 starter 会额外引入 model-openai、chat-client、 chat-memory 三个自动配置,可能生成与手写工厂、DatabaseChatMemory 冲突的 Bean --- pom.xml | 65 ++++++++------ .../wok/supportbot/SupportBotApplication.java | 5 +- .../chatmemory/FileBasedChatMemory.java | 85 ------------------- .../supportbot/config/ChatModelFactory.java | 4 +- .../converter/MessageConverter.java | 13 ++- 5 files changed, 53 insertions(+), 119 deletions(-) delete mode 100644 src/main/java/com/wok/supportbot/chatmemory/FileBasedChatMemory.java diff --git a/pom.xml b/pom.xml index ec46a77..9cd47c0 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.4 + 3.5.8 com.cdw @@ -14,7 +14,10 @@ 智能客服 17 - 1.0.0.4 + + 1.1.2 + + 1.1.2.2 false @@ -44,10 +47,12 @@ + org.springframework.ai spring-ai-bom - 1.0.1 + ${spring-ai.version} pom import @@ -66,6 +71,7 @@ + com.alibaba.cloud.ai spring-ai-alibaba-starter-dashscope @@ -79,7 +85,13 @@ - + org.springframework.ai spring-ai-starter-mcp-client @@ -91,7 +103,7 @@ - + io.modelcontextprotocol.sdk mcp @@ -102,7 +114,7 @@ cn.hutool hutool-all - 5.8.37 + 5.8.41 @@ -114,28 +126,24 @@ com.github.xiaoymin knife4j-openapi3-jakarta-spring-boot-starter - 4.4.0 + 4.5.0 - + + - com.github.victools - jsonschema-generator - 4.38.0 - - - - com.esotericsoftware - kryo - 5.6.2 + com.knuddels + jtokkit + 1.1.0 org.springframework.ai spring-ai-markdown-document-reader + org.projectlombok lombok - 1.18.36 true @@ -172,31 +180,31 @@ io.jsonwebtoken jjwt-api - 0.12.6 + 0.12.7 io.jsonwebtoken jjwt-impl - 0.12.6 + 0.12.7 runtime io.jsonwebtoken jjwt-jackson - 0.12.6 + 0.12.7 runtime - - - org.springframework.security - spring-security-oauth2-client - + com.baomidou mybatis-plus-spring-boot3-starter - 3.5.12 + 3.5.14 @@ -238,7 +246,8 @@ org.projectlombok lombok - 1.18.36 + + ${lombok.version} diff --git a/src/main/java/com/wok/supportbot/SupportBotApplication.java b/src/main/java/com/wok/supportbot/SupportBotApplication.java index 78caa3b..57aad0c 100644 --- a/src/main/java/com/wok/supportbot/SupportBotApplication.java +++ b/src/main/java/com/wok/supportbot/SupportBotApplication.java @@ -8,8 +8,9 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; /** * 主启动类 - * spring-security-oauth2-client 依赖已通过 pom.xml 补充, - * 确保 ToolCallingAutoConfiguration 不会抛出 ClassNotFoundException + *

+ * ChatModel / EmbeddingModel / VectorStore 均由项目内工厂手动构建(见 ChatModelFactory、 + * EmbeddingModelFactory、PgVectorStoreConfig),不使用 Spring AI 的自动配置。 */ @SpringBootApplication @EnableScheduling diff --git a/src/main/java/com/wok/supportbot/chatmemory/FileBasedChatMemory.java b/src/main/java/com/wok/supportbot/chatmemory/FileBasedChatMemory.java deleted file mode 100644 index 8fefb82..0000000 --- a/src/main/java/com/wok/supportbot/chatmemory/FileBasedChatMemory.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.wok.supportbot.chatmemory; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import org.objenesis.strategy.StdInstantiatorStrategy; -import org.springframework.ai.chat.memory.ChatMemory; -import org.springframework.ai.chat.messages.Message; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * 基于文件持久化的对话记忆 - */ -public class FileBasedChatMemory implements ChatMemory { - - private final String BASE_DIR; - private static final Kryo kryo = new Kryo(); - - static { - kryo.setRegistrationRequired(false); - // 设置实例化策略 - kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); - } - - // 构造对象时,指定文件保存目录 - public FileBasedChatMemory(String dir) { - this.BASE_DIR = dir; - File baseDir = new File(dir); - if (!baseDir.exists()) { - baseDir.mkdirs(); - } - } - - @Override - public void add(String conversationId, List messages) { - List conversationMessages = getOrCreateConversation(conversationId); - conversationMessages.addAll(messages); - saveConversation(conversationId, conversationMessages); - } - - @Override - public List get(String conversationId) { - return getOrCreateConversation(conversationId); - } - - @Override - public void clear(String conversationId) { - File file = getConversationFile(conversationId); - if (file.exists()) { - file.delete(); - } - } - - private List getOrCreateConversation(String conversationId) { - File file = getConversationFile(conversationId); - List messages = new ArrayList<>(); - if (file.exists()) { - try (Input input = new Input(new FileInputStream(file))) { - messages = kryo.readObject(input, ArrayList.class); - } catch (IOException e) { - e.printStackTrace(); - } - } - return messages; - } - - private void saveConversation(String conversationId, List messages) { - File file = getConversationFile(conversationId); - try (Output output = new Output(new FileOutputStream(file))) { - kryo.writeObject(output, messages); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private File getConversationFile(String conversationId) { - return new File(BASE_DIR, conversationId + ".kryo"); - } -} diff --git a/src/main/java/com/wok/supportbot/config/ChatModelFactory.java b/src/main/java/com/wok/supportbot/config/ChatModelFactory.java index 15438cc..03185a4 100644 --- a/src/main/java/com/wok/supportbot/config/ChatModelFactory.java +++ b/src/main/java/com/wok/supportbot/config/ChatModelFactory.java @@ -157,7 +157,7 @@ public class ChatModelFactory { } DashScopeApi api = apiBuilder.build(); - DashScopeChatOptions.DashscopeChatOptionsBuilder optionsBuilder = DashScopeChatOptions.builder() + DashScopeChatOptions.DashScopeChatOptionsBuilder optionsBuilder = DashScopeChatOptions.builder() .withModel(config.getModelName()); if (config.getTemperature() != null) { optionsBuilder.withTemperature(config.getTemperature()); @@ -352,7 +352,7 @@ public class ChatModelFactory { /** * 从 extraConfig 中读取高级参数并设置到 DashScopeChatOptions.Builder */ - private void applyDashScopeExtraConfig(AiModelConfig config, DashScopeChatOptions.DashscopeChatOptionsBuilder optionsBuilder) { + private void applyDashScopeExtraConfig(AiModelConfig config, DashScopeChatOptions.DashScopeChatOptionsBuilder optionsBuilder) { Map extra = config.getExtraConfig(); if (extra == null || extra.isEmpty()) return; diff --git a/src/main/java/com/wok/supportbot/converter/MessageConverter.java b/src/main/java/com/wok/supportbot/converter/MessageConverter.java index 45b6c73..3d2972c 100644 --- a/src/main/java/com/wok/supportbot/converter/MessageConverter.java +++ b/src/main/java/com/wok/supportbot/converter/MessageConverter.java @@ -110,12 +110,21 @@ public class MessageConverter { } case ASSISTANT -> { List toolCalls = extractToolCalls(cleanMetadata); - yield new AssistantMessage(text, cleanMetadata, toolCalls); + // Spring AI 1.1.x 起 AssistantMessage 带 metadata 的构造器为 protected,改用标准 builder + yield AssistantMessage.builder() + .content(text) + .properties(cleanMetadata) + .toolCalls(toolCalls) + .build(); } case SYSTEM -> new SystemMessage(text); case TOOL -> { List responses = extractToolResponses(cleanMetadata); - yield new ToolResponseMessage(responses, cleanMetadata); + // Spring AI 1.1.x 起 ToolResponseMessage 构造器为 protected,改用标准 builder + yield ToolResponseMessage.builder() + .responses(responses) + .metadata(cleanMetadata) + .build(); } }; }