上一篇文章我们把 Spring AI 空项目跑通了。今天,我们真正让它“开口说话”。

如果你已经成功跑通了空项目,现在肯定手痒了:到底怎么让 Java 应用跟 AI 聊起来? 别急,我们今天就用 DeepSeek 来完成这件事。

选择 DeepSeek 的原因很简单:国内直接访问、注册容易、价格亲民、兼容 OpenAI API 格式,对于我们上手学习来说简直是 perfect。而且你写完这段代码后,下次想换成 ChatGPT 或通义千问,只需要改配置文件里的两个参数,业务代码完全不动——这个我们下一篇就会验证。

好了,话不多说,打开你的 IDEA,我们开始写第一个 AI 对话接口。

一、从直觉出发:调用 AI 到底发生了什么?

在你写代码之前,我们先花 30 秒理解一下“调用 AI”在技术层面到底干了什么。

你的应用程序互联网DeepSeek 的服务器(上面跑着大模型)→ 返回答案

就像你点外卖:你(应用程序)打开 App 下单(发送 HTTP 请求),餐厅(DeepSeek)做好饭(模型推理),骑手把饭送到你手上(返回响应结果)。

Spring AI 在这里扮演的角色,就是把“下单、支付、追踪骑手”这些复杂的事情全部封装好,你只需要说一句“我要一碗面”,它就帮你把面端到面前。这个“下单”的动作,在代码里就是一个方法调用。

二、环境准备:就两步

如果上一篇的空项目你已经跑通,那环境基本是现成的。只需要确认两件事:

2.1 获取 DeepSeek API Key

访问 platform.deepseek.com,注册并登录。进入“API Keys”页面,点击“创建 API Key”,复制保存。

注意:Key 只会显示一次,请妥善保存!如果丢了只能重新创建。

充值三块就够了,足够我们学习使用。

2.2 配置 application.yml

打开 src/main/resources/application.yml,修改为 DeepSeek 的配置:

spring:
  application:
    name: spring-ai-hello-world

  ai:
    openai:
      api-key: ${DEEPSEEK_API_KEY}          # 从环境变量读取
      base-url: https://api.deepseek.com     # DeepSeek 官方地址
      chat:
        options:
          model: deepseek-chat               # DeepSeek 对话模型
          temperature: 0.7                   # 创造性参数

设置环境变量(不要硬编码在配置文件里!):

  • Mac / Linux:终端执行 export DEEPSEEK_API_KEY=sk-你的密钥
  • Windows PowerShell:执行 $env:DEEPSEEK_API_KEY="sk-你的密钥"
  • IDEA 运行配置:在 Run Configuration 的 Environment Variables 中添加 DEEPSEEK_API_KEY=sk-你的密钥

很多新手在这里出问题,后面我们会专门讲“为什么环境变量没生效”。

三、代码实战:编写第一个对话接口

我们的目标是:在浏览器输入 http://localhost:8080/chat?message=你好,页面直接返回 AI 的回复。

3.1 创建 ChatController

com.example.springaihelloworld 包下(与启动类同级)新建 ChatController.java

package com.example.springaihelloworld;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 第一个 AI 对话接口
 * 访问 http://localhost:8080/chat?message=你的消息
 */
@RestController
public class ChatController {

    private final ChatClient chatClient;

    // 构造器注入,Spring 会自动注入已配置好的 ChatClient Bean
    public ChatController(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    @GetMapping("/chat")
    public String chat(@RequestParam(defaultValue = "你好,请介绍一下你自己") String message) {
        // 调用 AI 模型,发送消息并获取回复
        return chatClient
                .prompt()                    // 开始构建一个提示(Prompt)
                .user(message)               // 设置用户消息内容
                .call()                      // 同步调用模型
                .content();                  // 提取回复的文本内容
    }
}

这就是全部代码,只有十来行。我们来逐行解释一下调用链:

方法 作用 大白话解释
.prompt() 创建一个 Prompt 对象 “我要给 AI 发消息了”
.user(message) 设置用户消息 “这是我要说的话”
.call() 同步发送请求,等待回复 “你帮我发过去,等它回我”
.content() 取出 AI 回复的正文 “把回复里的文字内容给我”

有没有发现,这和 Java 8 的 Optional 或者 Stream API 很像?链式调用,每一步都清晰明了。这就是 Spring AI 的流式(Fluent)API 风格。

3.2 启动类保持不变

启动类还是上一篇那个,什么额外注解都不需要:

package com.example.springaihelloworld;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringAiHelloWorldApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringAiHelloWorldApplication.class, args);
    }
}

Spring Boot 的自动配置会帮你搞定一切:读到 spring.ai.openai.api-key → 自动创建 ChatClient Bean → 你在 Controller 里直接用。

四、运行与演示:看到 AI 回复的真实时刻

4.1 启动项目

在 IDEA 中直接运行 main 方法,或者命令行:

mvn spring-boot:run

看到 Started SpringAiHelloWorldApplication 就说启动成功了。

4.2 测试接口

打开浏览器,访问:

http://localhost:8080/chat?message=你好,请用一句话介绍你自己

大约 1~3 秒后,你会看到类似这样的回复:

你好!我是 DeepSeek,由深度求索公司创造的 AI 助手,免费为你提供各种信息和帮助。

恭喜!你的 Java 应用已经成功和 AI 对话了!🎉

4.3 你也可以用 curl 测试

curl "http://localhost:8080/chat?message=用Java写一个HelloWorld"

返回结果里会包含 AI 给的代码示例。

4.4 试试不同的问题

http://localhost:8080/chat?message=3.14159 乘以 2 等于多少
http://localhost:8080/chat?message=简单解释一下什么是 Spring Boot
http://localhost:8080/chat?message=给我讲个程序员笑话

每次你都能得到一个合理的回答。这就是大语言模型的能力——它不是一个固定的“if-else”逻辑,而是能理解你的意图并生成内容。

五、常见问题与避坑提示

在实际运行中,新手最容易遇到下面几个问题。我们按出现频率排个序:

❌ 问题一:401 Unauthorized

org.springframework.ai.retry.NonTransientAiException: 401 Unauthorized

原因:API Key 没设置正确,或者根本就没读到。

排查步骤

  1. 确认环境变量是否已设置。终端执行 echo $DEEPSEEK_API_KEY(Mac/Linux)或 echo $env:DEEPSEEK_API_KEY(PowerShell)看有没有输出。
  2. 确认 application.yml 中写的是 ${DEEPSEEK_API_KEY},不要写成 ${DEEPSEEK_API_KEY: 这种多一个冒号的。
  3. 如果你是在 IDEA 里直接点的运行按钮,IDEA 不会自动读取系统终端的环境变量。你需要在 Run → Edit Configurations → Environment Variables 中手动添加 DEEPSEEK_API_KEY=sk-xxxx
  4. 最简单的测试办法:先用字符串硬编码试一下(但试完立刻改回去!)
# 仅用于临时测试!千万不要提交到 Git!
spring:
  ai:
    openai:
      api-key: sk-xxxxx   # 直接填入你的 key

如果能跑通,就说明环境变量没生效,重点排查第三步。

❌ 问题二:Connection timed out 或 UnknownHostException

java.net.ConnectException: Connection timed out

原因:网络连不上 api.deepseek.com

排查:先在终端 ping api.deepseek.com 看看能不能通。如果 ping 不通,可能需要检查网络代理或防火墙。有些公司内网会屏蔽外部 API,这时候可能需要配置代理。

Spring AI 的 OpenAI starter 支持代理配置,可以在 application.yml 中添加(一般学习环境不需要):

spring:
  ai:
    openai:
      proxy-url: http://你的代理地址:端口

❌ 问题三:返回乱码或中文显示为问号

可能原因:响应编码问题或 DeepSeek 模型选择了非 deepseek-chat 的模型(例如某些推理模型输出英文为主)。确认 model 参数写的是 deepseek-chat

❌ 问题四:回复很长,感觉很慢

这是正常的。模型推理需要时间,回复越长耗时越长。如果你只想快速验证,可以加一句提示词让 AI 简短回答:

@GetMapping("/chat")
public String chat(@RequestParam String message) {
    return chatClient
            .prompt()
            .user(message)
            // 引导 AI 简短回答,加快响应速度
            .system("请用简洁的语言回答,不超过100字")
            .call()
            .content();
}

⭐ 小贴士:defaultValue 的意义

我上面的代码给 message 参数加了 defaultValue = "你好,请介绍一下你自己"。这意味着访问 http://localhost:8080/chat 不传参数也能得到一个结果,方便你快手验证。

六、代码回顾:你真正学会了什么

虽然代码只有十来行,但背后涵盖的知识点其实不少。我们来盘点一下:

  1. ChatClient 是入口:所有对话操作都从这里开始。
  2. 链式调用.prompt().user().call().content() 是 Spring AI 对话的标准调用链。
  3. 同步 vs 异步.call() 是同步的,代码会阻塞直到 AI 返回;下一篇我们会讲流式 .stream(),打字机效果全靠它。
  4. 配置即切换:改个 base-urlmodel 就能换模型,代码零改动。这是 Spring AI 最强大的抽象能力。
  5. 环境变量管理密钥:永远不要把 API Key 写死在代码里。

到这里,你已经掌握了 Spring AI 最核心、最基础的对话调用模式。后续不管是加角色预设、实现流式输出,还是做结构化提取,都是在这个调用链上做扩展。

七、小结与下一步预告

本篇回顾

  • ✅ 配置 DeepSeek API Key,修改 application.yml
  • ✅ 编写第一个对话接口 /chat,用 ChatClient 发消息并接收回复
  • ✅ 理解了 .prompt().user().call().content() 调用链
  • ✅ 排查了最常见的配置错误

下一步预告

下一篇,我们要玩个“魔法”——无缝切换 ChatGPT

你会惊讶地发现,同一个 Controller、同一套代码,只需要改配置文件里的两个参数,你的应用就能跟 OpenAI 的 ChatGPT 聊起来。我们会一起体验 Spring AI 的“一次编写,到处接入”的魅力。


本系列博客基于 Spring AI 1.1.6 版本编写。建议在实际开发时查阅 Spring AI 官方文档 获取最新信息。DeepSeek API 文档见 platform.deepseek.com/api-docs

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐