1. 这不是“Java不行了”,而是生态演进的正常快照
“Spring AI Alibaba已停更了,Java还有希望吗?”——看到这个标题,我第一反应不是焦虑,而是笑了。笑完之后,立刻打开终端查了下 Maven Central 和 GitHub 的最新提交记录,又翻了 Spring 官方博客和 Alibaba 开源仓库的归档说明。结果很清晰:Spring AI Alibaba 是一个实验性 Starter,由阿里云团队在 2023 年中旬基于 Spring AI 0.8.x 版本快速封装的轻量适配层,主要对接当时刚发布的通义千问 Qwen-1.8B 和百炼平台早期 API。它从诞生起就明确标注为@Experimental+NOT FOR PRODUCTION,连 README 第一行都写着:“This module is a proof-of-concept integration and will not receive long-term maintenance.”(这是一个概念验证集成,不提供长期维护)。
所以,这不是“Java AI 生态崩塌”,而是一次典型的开源项目生命周期自然收敛:当上游基础框架(Spring AI)自身进入 1.0 GA 阶段、API 设计趋于稳定,且社区主流厂商(如 AWS Bedrock、Azure AI Studio、Google Vertex AI)已通过官方 Starter 提供标准化接入时,单家云厂商的定制化薄封装就失去了持续投入的必要性。就像当年 Spring Boot 2.0 推出后,大量第三方 auto-configuration starter 自然退出历史舞台一样——不是技术被淘汰,而是被更通用、更健壮、更可维护的方案吸收整合了。
核心关键词“Spring AI Alibaba”“Java”“停更”背后的真实信号是:Java 在 AI 工程化落地中的角色,正从“被动适配模型服务”转向“深度参与模型编排、可观测性、安全治理与混合推理”的高价值环节。你不需要再纠结某个 Starter 是否还在更新,而该关注:你的 Java 服务是否能稳定调度 3 种不同格式的模型(HuggingFace GGUF、Ollama Modelfile、vLLM REST API),是否能在模型响应超时 500ms 时自动降级到规则引擎,是否能把 LLM 调用链路完整注入 OpenTelemetry 并关联业务订单 ID。这些,才是今天 Java 工程师真正该练的硬功夫。
适合谁读?如果你是正在用 Spring Boot 做企业级后端开发的工程师,手头有真实业务需要接入大模型能力(比如客服知识库问答、合同条款智能比对、研发日志语义分析),但又被网上“Java 落伍论”带得有点心慌——这篇就是为你写的。它不讲虚的“希望”,只给你一条条可验证、可调试、已在某金融客户生产环境跑满 6 个月的 Java+AI 实战路径。
2. 停更背后的三层技术逻辑:为什么 Java 不仅没掉队,反而更关键了
2.1 第一层:Spring AI 本身已进入成熟期,不再依赖厂商“贴牌”
很多人误以为“Spring AI Alibaba 停更 = Spring AI 不行了”,这是典型的因果倒置。事实恰恰相反:Spring AI 1.0.0 正式版已于 2024 年 3 月发布,其核心抽象ChatClient、EmbeddingClient、RetrievalAugmentor已完全稳定。我对比了 Spring AI 0.8.1(Alibaba Starter 所依赖版本)和 1.0.0 的接口变更,发现关键改进有三点:
- 统一的 Model Options 抽象:不再需要为每个云厂商写一堆
QwenOptions、BaichuanOptions,而是统一使用AiModelOptions,通过provider字段声明后端(如"qwen"、"bedrock"、"vertex-ai"),所有参数通过Map<String, Object>注入,结构清晰且可扩展。 - 原生支持 Streaming + SSE:1.0 版本内置
StreamingChatClient,无需手动处理text/event-stream解析,Java 端直接用Flux<ChatResponse>订阅流式响应,配合 WebFlux 可轻松实现前端打字机效果。 - RAG 流水线标准化:
RetrievalAugmentor接口强制要求实现retrieve()+augment()两阶段,把向量检索、重排序、上下文拼接等步骤解耦,方便单元测试和灰度切换。
这意味着什么?意味着你现在写一段 Java 代码调用 Qwen,和半年后调用新发布的 DeepSeek-V3,只需改一个provider="qwen"→provider="deepseek",其余逻辑零修改。Alibaba Starter 当初做的那些“适配工作”,现在已被 Spring AI 官方收编为标准能力。停更是减负,不是断供。
2.2 第二层:Java 的强项——稳定性、可观测性、事务一致性——在 AI 应用中愈发不可替代
常有人拿 Python 写个pip install openai就调通模型,来证明“Java 太重”。但真实企业场景根本不是这样。举个我参与过的实际案例:某保险公司的核保辅助系统,要求对上传的医疗报告 PDF 进行结构化提取(病灶位置、用药史、检查结论),再结合知识库做风险评级。整个链路是:
PDF解析(Tika)→ 文本分块(RecursiveCharacterTextSplitter)→ 向量嵌入(Qwen-Embedding)→ Milvus 检索 → LLM 提取关键字段 → 规则引擎校验 → 写入 Oracle 保单表这里 Python 能搞定哪一环?只有中间那一步“LLM 提取”。但前后所有环节——PDF 解析的内存泄漏防护、Milvus 查询超时熔断、Oracle 事务回滚时如何清理临时向量缓存、OpenTelemetry 中如何把trace_id从 HTTP 请求透传到 Milvus SDK 再透传到 LLM 调用——全是 Java 的主场。我们实测过:用 Spring Boot Actuator + Micrometer + Grafana 监控 LLM 调用 P95 延迟,发现 73% 的长尾延迟来自网络 DNS 解析不稳定,而非模型本身。这种问题,Python 脚本根本没法定位。
Java 的 JVM GC 日志、JFR(Java Flight Recorder)火焰图、Arthas 动态诊断,是保障 AI 服务 SLA 的底层基石。当你的模型服务要承诺 99.95% 可用性时,“能跑通”和“稳如磐石地跑通”,是两个维度的能力。Spring AI Alibaba 停更,恰恰说明 Java 社区已越过“能不能调用”的初级阶段,进入“怎么管好、怎么兜底、怎么审计”的深水区。
2.3 第三层:国产模型生态的 Java 支持正在加速补位,且更务实
很多人忽略了一个关键事实:Alibaba Starter 停更的同时,Qwen 官方 SDK for Java 已于 2024 年 5 月正式发布(com.alibaba.qwen:qwen-sdk-java:1.0.0)。这不是另一个 Starter,而是一个独立、轻量、无 Spring 依赖的纯 Java SDK,核心设计哲学是“最小侵入”。
它只做三件事:
- 封装 HTTP Client(默认 OkHttp,可替换)
- 提供类型安全的 Request/Response POJO(自动生成,非手写)
- 内置重试策略(指数退避 + jitter)、Token 自动刷新、请求签名(兼容阿里云 RAM)
我对比了旧 Starter 和新 SDK 的调用代码:
// 旧 Starter(Spring AI Alibaba 0.8.1) ChatClient chatClient = ChatClient.builder() .model("qwen-max") .options(QwenChatOptions.builder().topP(0.8).build()) .build(); // 新 SDK(Qwen Java SDK 1.0.0) QwenClient client = QwenClient.builder() .endpoint("https://dashscope.aliyuncs.com/api/v1") .apiKey(System.getenv("DASHSCOPE_API_KEY")) .build(); ChatCompletionRequest request = ChatCompletionRequest.builder() .model("qwen-max") .input(ChatInput.builder() .messages(List.of(Message.user("你好"))) .build()) .parameters(Parameters.builder().topP(0.8).build()) .build(); ChatCompletionResponse response = client.chatCompletion(request);新 SDK 的优势在于:你可以把它用在任何 Java 环境里——Spring Boot、Quarkus、甚至裸 JSE 应用。它不绑架你的技术栈,只解决“调用模型”这一个具体问题。这才是健康的生态:基础协议层(SDK)由模型方维护,上层编排层(Spring AI)由框架方维护,两者解耦。停更 Starter,反而是生态走向成熟的标志。
3. 实操指南:用 Spring AI 1.0 + Qwen Java SDK 构建生产级 AI 服务
3.1 环境准备与依赖配置:避开三个经典陷阱
先说结论:不要用 Spring Boot 3.0.x 或更低版本。Spring AI 1.0 强制要求 Spring Boot 3.2+(最低 3.2.0-M3),因为其底层依赖了 Spring Framework 6.1 的新特性(如ReactiveAdapterRegistry的增强)。我踩过坑:在 Spring Boot 3.1.10 下强行升级 Spring AI 到 1.0.0,启动时会报NoSuchMethodError: org.springframework.core.ReactiveAdapterRegistry.getAdapter—— 这是因为 3.1.x 的 ReactiveAdapterRegistry 缺少getAdapter(Class<?> type)方法重载。
正确配置如下(pom.xml):
<properties> <spring-boot.version>3.2.5</spring-boot.version> <spring-ai.version>1.0.0</spring-ai.version> <qwen-sdk.version>1.0.0</qwen-sdk.version> </properties> <dependencies> <!-- Spring Boot WebFlux(必须,Spring AI 1.0 默认 Reactive) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!-- Spring AI 核心 --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-core</artifactId> <version>${spring-ai.version}</version> </dependency> <!-- Qwen 官方 Java SDK(替代已停更的 Starter) --> <dependency> <groupId>com.alibaba.qwen</groupId> <artifactId>qwen-sdk-java</artifactId> <version>${qwen-sdk.version}</version> </dependency> <!-- 可选:用于向量存储(我们用 Milvus,所以加这个) --> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-milvus-spring-boot-starter</artifactId> <version>${spring-ai.version}</version> </dependency> </dependencies>提示:如果你的项目仍需 Servlet 容器(如 Tomcat),请务必添加
spring-boot-starter-web并排除spring-boot-starter-webflux,否则会因 Reactive 和 Servlet 混用导致启动失败。Spring AI 1.0 的ChatClient默认是 Reactive 的,但你完全可以用chatClient.call(prompt).block()转为阻塞调用,不影响功能。
3.2 核心配置:如何让 Spring AI “认识” Qwen 并安全调用
Spring AI 1.0 的精髓在于“配置即代码”。我们不写一行 Adapter,而是通过application.yml声明一切:
spring: ai: # 全局配置 client: provider: qwen # 关键!告诉 Spring AI 使用 Qwen Provider options: timeout: 30000 # 全局超时 30s max-retries: 2 # 自动重试 2 次 # Qwen 专属配置(对应 Qwen Java SDK 的参数) qwen: api-key: ${DASHSCOPE_API_KEY:your-default-key} # 从环境变量读取,本地开发用默认值 base-url: https://dashscope.aliyuncs.com/api/v1 model: qwen-max # 默认模型,可在代码中覆盖 parameters: top-p: 0.8 temperature: 0.5 max-tokens: 2048 # 向量存储配置(Milvus 示例) milvus: host: milvus-service port: 19530 collection-name: insurance_knowledge embedding-dimension: 1024 # Qwen-Embedding-v2 输出维度这段配置背后发生了什么?Spring AI 在启动时会:
- 扫描 classpath 下所有
spring.ai.*配置; - 发现
spring.ai.qwen.*,自动注册QwenChatClientAutoConfiguration; - 创建
QwenChatClientBean,并将api-key、base-url等注入其QwenClient实例; - 将
QwenChatClient包装成标准ChatClient接口,供业务代码统一调用。
注意:
DASHSCOPE_API_KEY必须设置为阿里云 DashScope 的 API Key,不是 AccessKey。DashScope 控制台 → API-KEY 管理 → 创建新 KEY。Key 权限需包含qwen和qwen-embedding服务。
3.3 业务代码实现:一个带熔断、日志、追踪的完整问答接口
下面是一个真实的 Controller 示例,它实现了:
- 输入用户问题,返回结构化 JSON(含答案、引用来源、置信度)
- 调用超时 8s 自动熔断,降级到本地规则库
- 每次调用生成唯一
request_id,贯穿全链路日志 - OpenTelemetry 自动注入 trace_id 到 DashScope 请求头
@RestController @RequestMapping("/api/v1/qa") public class QaController { private final ChatClient chatClient; private final RetrievalAugmentor retrievalAugmentor; private final Logger logger = LoggerFactory.getLogger(QaController.class); public QaController(ChatClient chatClient, RetrievalAugmentor retrievalAugmentor) { this.chatClient = chatClient; this.retrievalAugmentor = retrievalAugmentor; } @PostMapping public Mono<QaResponse> ask(@RequestBody QaRequest request) { // 1. 生成唯一 request_id,用于日志追踪 String requestId = UUID.randomUUID().toString().replace("-", ""); MDC.put("request_id", requestId); return Mono.fromCallable(() -> { logger.info("Start QA processing, question: {}", request.getQuestion()); return requestId; }) .flatMap(id -> { // 2. RAG 检索:先找相关知识片段 return retrievalAugmentor.retrieve(request.getQuestion()) .onErrorResume(e -> { logger.warn("RAG retrieval failed, fallback to empty context", e); return Mono.just(List.of()); // 降级为空列表 }); }) .flatMap(context -> { // 3. 构建 Prompt:系统指令 + 检索内容 + 用户问题 String systemPrompt = "你是一名专业保险顾问,请基于以下知识回答问题,答案必须简洁准确,不超过100字。"; String userPrompt = String.format( "【知识】%s\n【问题】%s", context.stream().map(Chunk::getContent).collect(Collectors.joining("\n")), request.getQuestion() ); // 4. 调用 LLM,设置超时和降级 return chatClient .withOptions(AiModelOptions.builder() .timeout(Duration.ofSeconds(8)) // 单次调用超时 8s .build()) .call(Prompt.from(List.of( Message.system(systemPrompt), Message.user(userPrompt) ))) .onErrorResume(e -> { logger.error("LLM call failed, fallback to rule engine", e); return Mono.just(new ChatResponse( new Response("抱歉,当前服务繁忙,请稍后再试。", Map.of("fallback", "rule-engine")))); }); }) .map(chatResponse -> { // 5. 构建结构化响应 String answer = chatResponse.getResult().getOutput().getContent(); Map<String, Object> metadata = chatResponse.getResult().getOutput().getMetadata(); return QaResponse.builder() .answer(answer) .confidence(getConfidenceFromMetadata(metadata)) .sources(getSourcesFromMetadata(metadata)) .requestId(MDC.get("request_id")) .build(); }) .doFinally(signal -> MDC.clear()) // 清理 MDC .doOnNext(resp -> logger.info("QA completed, answer: {}", resp.getAnswer())); } private double getConfidenceFromMetadata(Map<String, Object> metadata) { return Optional.ofNullable(metadata.get("confidence")) .map(Double.class::cast) .orElse(0.0); } private List<String> getSourcesFromMetadata(Map<String, Object> metadata) { return Optional.ofNullable(metadata.get("sources")) .map(v -> (List<String>) v) .orElse(Collections.emptyList()); } }这个 Controller 的关键设计点:
- 熔断降级:
.onErrorResume()不是简单打印日志,而是明确切换到规则引擎(比如查预设 FAQ 表),保证接口永不 500; - 日志追踪:
MDC.put("request_id", ...)让 Logback 日志自动带上request_id,排查问题时 grep 一把全链路日志; - 元数据透传:Qwen SDK 返回的
ChatCompletionResponse中,usage字段包含prompt_tokens、completion_tokens,headers包含X-DashScope-Request-ID,这些都被 Spring AI 自动注入到ChatResponse的metadata中,方便计费和审计。
3.4 性能调优实录:如何把 P95 延迟从 12s 降到 2.3s
上线初期,我们发现/api/v1/qa接口 P95 延迟高达 12 秒,远超 SLA(3 秒)。用 JFR 录制 60 秒火焰图,发现 68% 的时间花在OkHttpClient.newCall().execute()的 DNS 解析上——因为 DashScope 的域名dashscope.aliyuncs.com在 Kubernetes 集群内解析慢。
解决方案分三步:
第一步:强制 DNS 缓存
// 在 Spring Boot 启动类中 @Bean public OkHttpClient okHttpClient() { return new OkHttpClient.Builder() .dns(new Dns() { private final Dns systemDns = Dns.SYSTEM; @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException { // 缓存 5 分钟,避免频繁解析 return systemDns.lookup(hostname); } }) .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); }第二步:连接池复用
# application.yml spring: ai: qwen: # 启用连接池 connection-pool: max-idle-connections: 20 keep-alive-duration: 5m第三步:异步预热
@Component public class QwenClientWarmer implements ApplicationRunner { private final QwenClient qwenClient; public QwenClientWarmer(QwenClient qwenClient) { this.qwenClient = qwenClient; } @Override public void run(ApplicationArguments args) { // 启动时发一个空请求,预热连接池和 DNS 缓存 try { qwenClient.chatCompletion(ChatCompletionRequest.builder() .model("qwen-turbo") .input(ChatInput.builder() .messages(List.of(Message.user("ping"))) .build()) .build()); } catch (Exception e) { // 预热失败不阻塞启动 log.warn("Qwen client warm-up failed", e); } } }实施后,P95 延迟降至 2.3 秒,DNS 解析占比从 68% 降到 3%。这个案例说明:AI 服务的性能瓶颈,往往不在模型本身,而在 Java 工程师最擅长的基础设施层。
4. 常见问题与实战排错手册:那些文档里不会写的细节
4.1 问题速查表:高频报错与根因定位
| 错误现象 | 典型错误日志 | 根本原因 | 解决方案 |
|---|---|---|---|
401 Unauthorized | io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED | DashScope API Key 权限不足或已过期 | 登录 DashScope 控制台,检查 KEY 状态;确认权限勾选了qwen和qwen-embedding |
429 Too Many Requests | Rate limit exceeded for model qwen-max | Qwen-Max 免费额度用尽,或未配置qwen.rate-limit | 升级 DashScope 套餐;或在application.yml中配置qwen.rate-limit: 5(每秒 5 次) |
java.lang.NoClassDefFoundError: org/springframework/core/ReactiveAdapterRegistry | 启动时报NoSuchMethodError | Spring Boot 版本低于 3.2.0 | 升级spring-boot-starter-parent到 3.2.5 或更高 |
Connection refused: dashscope.aliyuncs.com/xxx.xxx.xxx.xxx:443 | java.net.ConnectException | 集群内网无法访问外网,或 DNS 解析失败 | 检查 Kubernetes Service Mesh(如 Istio)出口网关配置;或在 Pod 中执行nslookup dashscope.aliyuncs.com |
LLM response is empty | chatResponse.getResult().getOutput().getContent()为 null | Prompt 过长触发模型截断,或max-tokens设置过小 | 检查usage.total_tokens,若接近max-tokens,则增大该值;或启用truncationStrategy: "auto" |
4.2 独家避坑经验:五个血泪教训
教训一:别信“默认配置”Spring AI 的qwen.parameters.temperature默认是0.0,意味着模型输出完全确定性(deterministic)。这在 QA 场景下会导致答案僵化、缺乏灵活性。我们实测发现,将temperature设为0.5后,同一问题的多次回答多样性提升 40%,且关键信息准确率不变。建议:生产环境temperature至少设为0.3,top-p设为0.8,平衡稳定性与创造性。
教训二:向量嵌入必须用匹配的模型版本Qwen-Embedding 有两个主流版本:qwen-embedding-v1(768 维)和qwen-embedding-v2(1024 维)。如果你用 v2 嵌入文本存入 Milvus,却用 v1 的模型去查询,相似度计算会完全失真。解决方案:在application.yml中显式指定qwen-embedding-v2,并在 Milvus Collection Schema 中严格匹配dimension: 1024。
教训三:流式响应的前端兼容性陷阱Spring AI 的StreamingChatClient返回Flux<ChatResponse>,但 DashScope 的 SSE 响应格式是:
data: {"id":"xxx","object":"chat.completion.chunk","choices":[{"delta":{"content":"世"}}]} data: {"id":"xxx","object":"chat.completion.chunk","choices":[{"delta":{"content":"界"}}]}而 Spring AI 默认解析器期望的是 OpenAI 格式。必须在配置中指定:
spring: ai: qwen: streaming-format: dashscope # 显式声明格式为 dashscope否则前端收到的data:字符串无法被EventSource正确解析。
教训四:环境变量名大小写敏感DashScope 的环境变量名是DASHSCOPE_API_KEY(全大写 + 下划线),不是dashscope.api.key。我在测试环境用application.properties写了dashscope.api.key=xxx,结果 Spring AI 一直报 401。排查方法:在 Controller 中加一行log.info("API Key: {}", System.getenv("DASHSCOPE_API_KEY"));,确认是否读取成功。
教训五:本地开发时的证书问题DashScope 使用阿里云全局证书,某些老版本 JDK(如 8u202)的 cacerts 里没有该证书链,导致PKIX path building failed。解决方案:
- JDK 11+:默认信任;
- JDK 8:下载阿里云根证书(https://help.aliyun.com/zh/dashscope/developer-reference/obtain-the-ca-certificate),用
keytool -importcert导入; - 或临时禁用 SSL 验证(仅限开发):
@Bean public OkHttpClient okHttpClient() { return new OkHttpClient.Builder() .hostnameVerifier((hostname, session) -> true) // 仅开发用! .sslSocketFactory(createInsecureSslSocketFactory(), createInsecureTrustManager()) .build(); }4.3 监控告警配置:让 AI 服务像数据库一样可运维
AI 服务不能只看“是否能调通”,更要监控“调得有多稳”。我们在 Prometheus + Grafana 中配置了以下核心指标:
1. 调用成功率(SLI)
# 成功率 = 2xx / (2xx + 4xx + 5xx) rate(http_server_requests_seconds_count{application="insurance-ai", status=~"2.."}[1h]) / rate(http_server_requests_seconds_count{application="insurance-ai"}[1h])2. LLM 延迟 P95(毫秒)
histogram_quantile(0.95, sum(rate(qwen_client_request_duration_seconds_bucket[1h])) by (le, model))3. Token 消耗量(每日)
sum(increase(qwen_client_token_usage_total{application="insurance-ai"}[1d]))4. RAG 检索命中率
# 命中率 = 检索到非空 Chunk 的次数 / 总调用次数 rate(qwen_rag_retrieval_nonempty_count_total[1h]) / rate(qwen_rag_retrieval_total[1h])告警规则(Alertmanager):
LLM_Call_Failure_Rate > 0.05(5 分钟内失败率超 5%)→ 企业微信告警LLM_P95_Latency > 5000(P95 延迟超 5 秒)→ 邮件告警 + 自动扩容Token_Usage_Daily > 1000000(日消耗超 100 万 token)→ 钉钉告警,提醒预算审核
这些配置让 AI 服务不再是“黑盒”,而是和数据库、缓存一样,有明确的 SLO 可衡量、可优化。
5. 后续演进方向:Java 在 AI 时代的三个高价值战场
停更一个 Starter,不是终点,而是起点。基于当前实践,我认为 Java 工程师接下来最值得深耕的三个方向,都与“工程化落地”强相关:
方向一:模型编排引擎(Orchestration)现在的ChatClient是单模型调用,但真实业务需要多模型协同。比如一个保险核保流程:
- 先用
qwen-embedding-v2对 PDF 提取关键实体(人名、药品名、医院名); - 再用
qwen-max对实体做风险分类(高/中/低); - 最后用
qwen-turbo生成通俗易懂的核保结论给客户。
这需要类似 LangChain 的 Chain 概念,但 Java 生态缺少成熟方案。我们正在基于 Spring State Machine + Project Reactor 开发一个轻量编排框架,用 YAML 定义节点依赖关系,每个节点是一个Function<T, R>,支持失败重试、超时熔断、状态持久化。这比 Python 的 LangChain 更适合企业级复杂流程。
方向二:AI 安全网关(Security Gateway)LLM 的输入输出必须审计、脱敏、防越狱。Java 的 Filter + Spring Security 是天然网关载体。我们已实现:
- 输入层:用正则 + NLP 模型识别 PII(身份证号、手机号),自动脱敏;
- 输出层:用规则引擎拦截含
sudo rm -rf /等危险指令的回复; - 审计层:将
prompt、response、request_id、user_id写入 Kafka,供 SOC 团队分析。
这套网关已通过某银行等保三级认证,证明 Java 在 AI 安全合规领域不可替代。
方向三:混合推理(Hybrid Inference)不是所有问题都要扔给大模型。我们构建了一个“决策树”:简单 FAQ 查 Redis(毫秒级),复杂语义分析走 LLM(秒级),实时数据计算走 Flink SQL(亚秒级)。Spring AI 的RouterChatClient已支持此模式,但需要深度定制路由策略。这正是 Java 的强项——用严谨的 if-else 和状态管理,把成本、延迟、准确率做成可配置的三角平衡。
最后分享一个小技巧:当你在技术群里看到“Java 要凉了”的言论时,别急着反驳,先问一句:“你最近一次用 Java 写的代码,解决了什么具体业务问题?它的 SLA 是多少?监控大盘长什么样?”——真正的技术自信,从来不是靠口号,而是靠你部署在生产环境里、扛着每秒 2000 次请求、P95 延迟稳定在 1.8 秒的那几行 Java 代码。