# 把 Spring AI 的 OpenAI starter 接到 Router One

> https://router.one/zh/integrations/spring-ai 的 Markdown 镜像，供 AI 助手与爬虫使用。Router One 是 OpenAI 兼容的统一 LLM API 网关。
> 最后更新：2026-09-07

Spring AI 为 Spring Boot 应用提供统一的 ChatClient 模型 API。它的 OpenAI starter 发送的是 Chat Completions 请求，所以一把 Router One Key 就能调用目录里在 /v1/chat/completions 上提供服务的所有聊天模型，每次请求都有成本 Trace。不同版本线唯一的差别在 base-url：Spring AI 2.0.x 把这个值交给官方 openai-java SDK，由 SDK 自行拼接 /chat/completions；1.x 则自己拼接 /v1/chat/completions。本指南两条版本线都覆盖，最后用一次普通调用和一次流式输出做验证。

## 引入 Spring AI BOM 和 OpenAI starter

Spring AI 的正式版发布在 Maven Central，不需要额外配置仓库。导入 spring-ai-bom，再添加 spring-ai-starter-model-openai；这个 starter 会带上 OpenAI 聊天模型实现、自动配置，以及本指南要注入的 ChatClient.Builder。BOM 版本要和你的 Spring Boot 版本线匹配：Spring AI 2.0.x（写作时为 2.0.1）支持 Spring Boot 4.0.x 和 4.1.x，Spring AI 1.1.x（1.1.8）支持 Spring Boot 3.4.x 和 3.5.x。两条版本线的依赖坐标相同，只有版本号不同。

`pom.xml`

```xml
<!-- pom.xml: Spring AI 2.0.x on Spring Boot 4.x; use 1.1.8 with Spring Boot 3.4/3.5 -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-bom</artifactId>
      <version>2.0.1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
  </dependency>
</dependencies>
```

## 把 Spring AI 配置到 Router One base URL

Spring AI 2.0.x 只需在 src/main/resources/application.yml 里设置三个属性。base-url 填 https://api.router.one/v1，要带 /v1：2.0 会把这个值原样传给 openai-java SDK，由 SDK 自行在后面拼接 /chat/completions（SDK 自己的默认地址本来就以 /v1 结尾，虽然 2.0.1 文档的属性表仍写着旧的纯主机默认值）。api-key 通过 Spring 占位符读取 ROUTER_ONE_API_KEY，这个变量名是本指南定义的，刻意不用 OPENAI_API_KEY——因为属性留空时，2.0 会回退读取环境里的 OPENAI_API_KEY 和 OPENAI_BASE_URL。chat.model 填目录里的精确模型 ID，若 ID 自带 provider 前缀也要保留；2.0 去掉了原来 chat.options.* 里的 options 这一层，旧名字仍能绑定，但已标记为弃用：

`application.yml`

```yaml
# src/main/resources/application.yml: Spring AI 2.0.x (Spring Boot 4.x)
spring:
  ai:
    openai:
      base-url: https://api.router.one/v1
      api-key: ${ROUTER_ONE_API_KEY}
      chat:
        model: <model-id-from-/models>

# Shell (macOS/Linux) before starting the app:
# export ROUTER_ONE_API_KEY=sk-your-router-one-key
```

## Spring AI 1.x：主机根地址加 completions-path

Spring AI 1.0.x 和 1.1.x 自己拼接请求地址：base-url 加上 chat.completions-path 属性，后者默认值是 /v1/chat/completions。所以在 1.x 上，base-url 填不带 /v1 的主机根地址 https://api.router.one，模型 ID 写在 chat.options.model 下。如果这里仍然带着 /v1，请求会被发到 /v1/v1/chat/completions。下面的 completions-path 一行就是默认值，写出来只是为了让拼接方式一目了然。另外，1.x 会通过属性默认把 temperature 设为 0.7，而 2.0 只在你设置时才发送 temperature：

`application.yml (Spring AI 1.x)`

```yaml
# application.yml: Spring AI 1.0.x / 1.1.x (Spring Boot 3.4 / 3.5)
spring:
  ai:
    openai:
      base-url: https://api.router.one
      api-key: ${ROUTER_ONE_API_KEY}
      chat:
        completions-path: /v1/chat/completions
        options:
          model: <model-id-from-/models>
```

## 各版本线该填什么

两条版本线都是 Maven Central 上的正式版（写作时为 2.0.1 和 1.1.8），依赖坐标相同；1.0 之前里程碑版本使用的 spring-ai-openai-spring-boot-starter 这个名字止步于 1.0.0-M6。按你运行的 Spring Boot 版本线对照下表：

| Spring AI | Spring Boot | spring.ai.openai.base-url | 模型属性 | 路径由谁拼接 |
| --- | --- | --- | --- | --- |
| 2.0.x（2.0.1） | 4.0.x / 4.1.x | https://api.router.one/v1 | spring.ai.openai.chat.model | openai-java SDK 拼接 /chat/completions |
| 1.1.x（1.1.8）、1.0.x（1.0.9） | 3.4.x / 3.5.x | https://api.router.one | spring.ai.openai.chat.options.model | spring.ai.openai.chat.completions-path，默认 /v1/chat/completions |

## 用 ChatClient 各做一次普通调用和流式调用

注入自动配置的 ChatClient.Builder，构建 ChatClient，先做一次普通 call()——模型和端点都来自上面的属性，代码里不用重复。然后调用 stream().content()，它返回 Reactor 的 Flux<String>；Spring AI 的 ChatClient 文档说明流式输出运行在响应式技术栈上。启动应用，确认两段输出都正常，再去加工具调用、对话记忆或结构化输出；这些都留在你的应用里，网关只记录每次模型请求：

`RouterOneSmokeTest.java`

```java
package com.example.demo;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
class RouterOneSmokeTest {

  @Bean
  CommandLineRunner routerOneSmokeTest(ChatClient.Builder builder) {
    ChatClient chatClient = builder.build();
    return args -> {
      // One plain call first; the model comes from spring.ai.openai.chat.model
      String reply = chatClient.prompt()
          .user("Reply with one short greeting.")
          .call()
          .content();
      System.out.println(reply);

      // Then streaming: a Flux<String> from the same ChatClient
      chatClient.prompt()
          .user("Count from 1 to 5, one number per line.")
          .stream()
          .content()
          .doOnNext(System.out::print)
          .blockLast();
    };
  }
}
```

## Spring AI 该填哪个模型 ID？

从 /models 页复制精确的模型 ID，保留大小写、连字符和版本后缀，不要用展示名称代替。打开该模型的详情页，核对支持的 API 端点、上下文窗口和工具调用等能力，再与 Spring AI 当前选择的 provider 和功能对应。模型出现在目录里，不等于当前客户端能调用它的所有功能。建议为每个工具单独建 API Key，并设置 maxSpend 消费上限。

## Spring AI 用的是哪种 API 协议？

OpenAI 兼容描述的是接口格式，不能据此推断 Chat Completions（/v1/chat/completions）、Responses（/v1/responses）和 Anthropic Messages（/v1/messages）可以互换。先核对工具当前版本、provider 配置和实际请求路径，再查模型详情与 API 兼容性事实页。一次普通对话成功，也不能证明服务端工具、历史状态或文件编辑功能都受支持。

## 在 trace 里验证 Spring AI 的调用

先在 Spring AI 发出一次简单文本请求，再到 Dashboard → Logs 按时间、模型和 request_id 核对 trace：tokens、花费、延迟和状态码。成功后再分别验证流式输出、工具调用和多轮历史。失败时保留实际请求路径、完整错误消息及 request_id；没有对应日志时，先查客户端配置和网络，不能仅凭客户端报错认定是网关或上游故障。

## 常见问题

### Spring AI 的 OpenAI starter 用的是 Responses API 吗？

不是。这个 starter 把 Chat Completions 请求发到 /v1/chat/completions；Spring AI 2.0.1 文档明确写着 Responses API 是另一个端点，当前客户端不支持。因此只存在于 /v1/responses 上的功能（托管工具、previous_response_id、对话状态）在这个 starter 里用不到，模型是否支持 Responses 在这里也不重要——要看的是模型详情页是否列出 POST /v1/chat/completions。

### 从 Spring AI 1.x 升到 2.0 之后请求变成 404，哪里变了？

变了两处。一是 base-url 现在必须带 /v1：2.0 把它直接交给 openai-java SDK，也不再有 completions-path 属性；沿用旧的主机根地址时，请求会发到 /chat/completions，网关返回 404 的 not_found 错误，消息里会直接说明 OpenAI 兼容客户端需要以 /v1 结尾的 base URL。二是 chat.options.* 属性改成了 chat.*，旧名字仍能绑定，但已标记为弃用并将移除。两处都改完后，重新跑一次普通调用。

### 为什么一次 ChatClient 调用在 Logs 里出现好几条请求？

客户端重试。2.0 里 openai-java SDK 会对 408、409、429、5xx 响应和连接错误重试，次数上限是 spring.ai.openai.max-retries（文档默认 3）；1.x 则由 spring.ai.retry 重试模板处理，上限是 spring.ai.retry.max-attempts（文档默认 10），默认不重试 4xx，除非打开 on-client-errors。每一次到达网关的尝试都是独立请求，有各自的 Trace 和费用；而网关在同一次请求内做的同系列故障转移只算一条 Trace。批处理任务建议调低重试次数，并给应用单独配一把设了 maxSpend 的 Key。

### 调用 Claude 系列模型需要换 Anthropic starter 吗？

本指南的配置不需要。网关的 /v1/chat/completions 服务目录里的所有聊天模型，从 /models 复制的 Claude 系列 ID 和其他模型一样填进 chat.model 即可。Spring AI 的 Anthropic starter 走 /v1/messages 的 Anthropic Messages 格式，用的是自己的 spring.ai.anthropic.* 属性，不在本指南范围内，需要单独验证。

### 1.x 上第一次调用就报 400，错误里提到 temperature，是网关的问题吗？

通常不是。1.x 默认通过属性发送 temperature 0.7，而 Spring AI 文档说明部分 GPT-5 系列模型不接受 temperature 参数。到 Logs 里看完整错误和 request_id：点名该参数的 400 是模型拒绝了它。2.0 只在你设置时才发送 temperature。针对该模型调整 temperature 设置即可，不要去改 base-url 或模型 ID。

### Spring AI 能通过网关用哪些模型？

选用当前目录中同时支持 Spring AI 所用端点和所需功能的模型。精确 ID、当前单价与能力以 /models 及模型详情为准；不要仅按 GPT、Claude 等系列名判断兼容性。客户端能列出模型，只证明模型发现成功，仍需验证实际调用。

### 能列出模型，但调用报 400 或 404，怎么办？

先记录实际请求路径和错误消息，再核对精确模型 ID。400 可能是参数、工具类型或模型与端点不匹配；404 可能是请求路径或资源不存在，不能直接判定模型下线。若错误提示 must be called via，按它指明的端点调整客户端 provider，或换用支持当前端点的模型。不要在所有工具里统一增删 /v1 或 /chat/completions。

### 中国大陆能直连吗？

能。网关在大陆可直连、无需 VPN，配置与全球环境完全一致。

### 报 401/402/403/429 怎么排查？

先到 Dashboard → Logs 核对请求及错误消息。401 查 Key 是否传入和有效；402 查钱包余额与 maxSpend；403 查 Key 权限和访问限制；429 查请求频率、token 限额及上游限流，按错误来源处理。保留 request_id，再按错误码速查页逐项排查。

## 相关页面

- 全部接入指南：https://router.one/zh/integrations
- Spring AI 的 API 错误排查：https://router.one/zh/llm-api-error-codes
- API 兼容性：端点与功能对照：https://router.one/zh/facts/api-compatibility.md
- Responses API 配置与限制：https://router.one/zh/codex-responses-api
- Cline 接入：https://router.one/zh/integrations/cline
- Aider 接入：https://router.one/zh/integrations/aider
- LangChain ChatOpenAI 接入：https://router.one/zh/integrations/langchain
- OpenAI SDK 接入：https://router.one/zh/integrations/openai-sdk
- 网关的流式输出：https://router.one/zh/llm-streaming
- Spring AI 官方文档：OpenAI Chat 属性（2.0）：https://docs.spring.io/spring-ai/reference/api/chat/openai-chat.html
- Spring AI 官方文档：OpenAI Chat 属性（1.1）：https://docs.spring.io/spring-ai/reference/1.1/api/chat/openai-chat.html
- Spring AI 官方文档：ChatClient API：https://docs.spring.io/spring-ai/reference/api/chatclient.html
- Spring AI 官方文档：升级说明：https://docs.spring.io/spring-ai/reference/upgrade-notes.html
- 网关层负责什么：https://router.one/zh/llm-api-gateway
- OpenAI 兼容 API：https://router.one/zh/openai-compatible-api
- API 文档：https://router.one/zh/docs
- 本页规范地址：https://router.one/zh/integrations/spring-ai
- 模型与每模型 token 价格：https://router.one/zh/models （markdown：https://router.one/zh/models.md ）
- 定价：https://router.one/zh/pricing
- API 文档（markdown）：https://router.one/zh/docs.md
- 公司事实（markdown）：https://router.one/zh/facts/company.md
