Spring AI 实战教程(二):快速入门
2025-07-16·4 分钟阅读
Spring AI 实战教程(二):快速入门
前言
在上一章中,我们了解了 Spring AI 的整体架构和核心概念。本章将从实践出发,手把手搭建一个完整的 Spring AI 应用。通过构建一个智能对话服务,你将掌握 Spring AI 的核心开发流程。
项目初始化
方式一:Spring Initializr(推荐)
访问 Spring Initializr,配置如下:
项目配置:
├── Project: Maven
├── Language: Java
├── Spring Boot: 3.4.x
├── Packaging: Jar
├── Java: 21
│
├── Dependencies:
│ ├── Spring Web
│ ├── Spring AI OpenAI (或选择其他模型提供商)
│ └── Spring Boot DevTools (开发时热部署)
点击 "Generate" 下载项目压缩包,解压后导入 IDE。
方式二:命令行创建
# 使用 curl 下载
curl https://start.spring.io/starter.zip \
-d type=maven-project \
-d language=java \
-d bootVersion=3.4.0 \
-d baseDir=spring-ai-demo \
-d groupId=com.example \
-d artifactId=spring-ai-demo \
-d name=spring-ai-demo \
-d packageName=com.example.springai \
-d javaVersion=21 \
-d dependencies=web,openai,devtools \
-o spring-ai-demo.zip
# 解压
unzip spring-ai-demo.zip -d .
cd spring-ai-demo
方式三:IDE 内置
IntelliJ IDEA:
- File → New → Project
- 选择 "Spring Initializr"
- 填写项目信息
- 在 Dependencies 中搜索并添加:
- Spring Web
- Spring AI OpenAI
项目结构
创建完成后的项目结构:
spring-ai-demo/
├── pom.xml # Maven 配置
├── src/
│ ├── main/
│ │ ├── java/com/example/springai/
│ │ │ ├── SpringAiDemoApplication.java # 启动类
│ │ │ ├── controller/
│ │ │ │ └── ChatController.java # REST 控制器
│ │ │ ├── service/
│ │ │ │ └── ChatService.java # 聊天服务
│ │ │ └── config/
│ │ │ └── AiConfig.java # AI 配置
│ │ └── resources/
│ │ ├── application.yml # 应用配置
│ │ └── prompts/ # 提示词模板
│ │ └── system-prompt.st
│ └── test/
│ └── java/com/example/springai/
│ └── SpringAiDemoApplicationTests.java
└── HELP.md
依赖配置
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-ai-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-ai-demo</name>
<description>Spring AI Demo Project</description>
<properties>
<java.version>21</java.version>
<spring-ai.version>1.0.0</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<!-- 开发工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Gradle (build.gradle)
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.0'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
ext {
set('springAiVersion', "1.0.0")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.ai:spring-ai-bom:${springAiVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
应用配置
application.yml
spring:
application:
name: spring-ai-demo
# AI 配置
ai:
openai:
api-key: ${OPENAI_API_KEY} # 从环境变量读取
base-url: https://api.openai.com # 可选,默认值
# Chat 模型配置
chat:
enabled: true
options:
model: gpt-4o-mini # 使用较便宜的模型进行测试
temperature: 0.7
max-tokens: 1000
# Embedding 模型配置(可选)
embedding:
enabled: true
options:
model: text-embedding-3-small
# 服务配置
server:
port: 8080
# 日志配置
logging:
level:
org.springframework.ai: DEBUG
com.example.springai: DEBUG
# 生产环境可以创建 application-prod.yml
多环境配置
# application-dev.yml - 开发环境
spring:
ai:
openai:
chat:
options:
model: gpt-4o-mini # 便宜的模型用于开发
# application-prod.yml - 生产环境
spring:
ai:
openai:
chat:
options:
model: gpt-4o # 生产使用更强模型
temperature: 0.3 # 更稳定的输出
核心代码实现
1. 启动类
package com.example.springai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAiDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiDemoApplication.class, args);
}
}
2. 聊天服务
package com.example.springai.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
@Service
public class ChatService {
private final ChatClient chatClient;
public ChatService(ChatModel chatModel) {
this.chatClient = ChatClient.builder(chatModel)
.defaultSystem("""
你是一个友好、专业的AI助手。
请用简洁、清晰的语言回答用户的问题。
如果不确定答案,请诚实地说明。
""")
.build();
}
/**
* 简单对话
*/
public String chat(String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
/**
* 带系统提示的对话
*/
public String chatWithSystem(String systemPrompt, String message) {
return ChatClient.create(chatClient.getChatModel())
.prompt()
.system(systemPrompt)
.user(message)
.call()
.content();
}
/**
* 流式响应
*/
public Flux<String> chatStream(String message) {
return chatClient.prompt()
.user(message)
.stream()
.content();
}
}
3. REST 控制器
package com.example.springai.controller;
import com.example.springai.service.ChatService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/api/chat")
public class ChatController {
private final ChatService chatService;
public ChatController(ChatService chatService) {
this.chatService = chatService;
}
/**
* 简单对话接口
* POST /api/chat
* Body: { "message": "你好" }
*/
@PostMapping
public ChatResponse chat(@RequestBody ChatRequest request) {
String response = chatService.chat(request.message());
return new ChatResponse(response);
}
/**
* 流式对话接口 (SSE)
* GET /api/chat/stream?message=你好
*/
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String message) {
return chatService.chatStream(message);
}
/**
* 带角色设定的对话
* POST /api/chat/role
*/
@PostMapping("/role")
public ChatResponse chatWithRole(@RequestBody RoleChatRequest request) {
String response = chatService.chatWithSystem(
"你是一个" + request.role() + ",请以该身份回答问题。",
request.message()
);
return new ChatResponse(response);
}
// DTOs
public record ChatRequest(String message) {}
public record ChatResponse(String content) {}
public record RoleChatRequest(String role, String message) {}
}
4. 配置类(可选)
package com.example.springai.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiConfig {
@Bean
public ChatClient chatClient(ChatModel chatModel) {
return ChatClient.builder(chatModel)
.defaultSystem("""
你是一个专业的技术顾问。
请用清晰、专业的方式回答技术问题。
必要时提供代码示例。
""")
.build();
}
}
运行与测试
启动应用
# 设置环境变量
export OPENAI_API_KEY=your-api-key-here
# 启动应用
mvn spring-boot:run
# 或使用 Gradle
gradle bootRun
测试 API
方式一:curl 命令
# 简单对话
curl -X POST http://localhost:8080/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "你好,请介绍一下 Spring AI"}'
# 流式对话
curl -N http://localhost:8080/api/chat/stream?message=讲一个笑话
# 角色对话
curl -X POST http://localhost:8080/api/chat/role \
-H "Content-Type: application/json" \
-d '{"role": "资深Java开发者", "message": "如何学习Spring框架?"}'
方式二:HTTP 文件(IntelliJ IDEA)
### 简单对话
POST http://localhost:8080/api/chat
Content-Type: application/json
{
"message": "什么是 RAG?请简单解释。"
}
### 流式对话
GET http://localhost:8080/api/chat/stream?message=给我讲个笑话
Accept: text/event-stream
### 角色对话
POST http://localhost:8080/api/chat/role
Content-Type: application/json
{
"role": "资深架构师",
"message": "如何设计一个高并发系统?"
}
自动配置原理
Spring AI 的自动配置机制是其核心特性之一:
自动配置类
Spring AI 自动配置流程:
┌─────────────────────────────────────────────────────────────┐
│ spring.factories │
│ org.springframework.ai.autoconfigure.openai.OpenAiAuto │
│ Configuration │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 检测配置属性 (spring.ai.openai.*) │
│ ↓ │
│ 2. 创建 OpenAiApi (API 客户端) │
│ ↓ │
│ 3. 创建 ChatModel (聊天模型) │
│ ↓ │
│ 4. 创建 EmbeddingModel (嵌入模型) │
│ ↓ │
│ 5. 注入到 Spring 容器 │
│ │
└─────────────────────────────────────────────────────────────┘
条件装配
// Spring AI 内部实现示意
@AutoConfiguration
@ConditionalOnClass(OpenAiApi.class)
@ConditionalOnProperty(prefix = "spring.ai.openai", name = "api-key")
public class OpenAiAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public OpenAiApi openAiApi(OpenAiConnectionProperties properties) {
return new OpenAiApi(properties.getBaseUrl(), properties.getApiKey());
}
@Bean
@ConditionalOnMissingBean
public ChatModel chatModel(OpenAiApi api, OpenAiChatProperties properties) {
return new OpenAiChatModel(api, properties.getOptions());
}
}
自定义覆盖
你可以通过定义自己的 Bean 来覆盖默认配置:
@Configuration
public class CustomAiConfig {
@Bean
public ChatClient.Builder chatClientBuilder(ChatModel chatModel) {
return ChatClient.builder(chatModel)
.defaultOptions(ChatOptionsBuilder.builder()
.withModel("gpt-4o")
.withTemperature(0.5)
.build());
}
}
使用 Ollama 本地模型
如果没有 OpenAI API Key,可以使用 Ollama 运行本地模型:
安装 Ollama
# macOS/Linux
curl -fsSL https://ollama.com/install.sh | sh
# 下载模型
ollama pull llama3.2
ollama pull qwen2.5
# 启动服务
ollama serve
添加依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
配置
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: llama3.2
options:
temperature: 0.7
常见问题排查
1. API Key 配置问题
# 错误信息
"API key not found"
# 解决方案
# 方式一:环境变量
export OPENAI_API_KEY=sk-xxx
# 方式二:配置文件(不推荐生产使用)
spring:
ai:
openai:
api-key: sk-xxx
# 方式三:启动参数
java -jar app.jar --spring.ai.openai.api-key=sk-xxx
2. 网络超时
spring:
ai:
openai:
chat:
options:
connect-timeout: 60000 # 连接超时 60s
read-timeout: 120000 # 读取超时 120s
3. Token 超限
// 控制输出长度
chatClient.prompt()
.user(message)
.call()
.content();
// 或在配置中设置
spring:
ai:
openai:
chat:
options:
max-tokens: 500
4. 响应为空
检查日志级别,开启 DEBUG 日志:
logging:
level:
org.springframework.ai: DEBUG
org.springframework.web.client: DEBUG
单元测试
package com.example.springai;
import com.example.springai.service.ChatService;
import org.junit.jupiter.api.Test;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@SpringBootTest
class ChatServiceTest {
@MockBean
private ChatModel chatModel;
@Autowired
private ChatService chatService;
@Test
void testChat() {
// Mock 响应
when(chatModel.call(any(Prompt.class)))
.thenReturn(new ChatResponse(List.of(
new Generation("这是一个测试响应")
)));
// 执行测试
String response = chatService.chat("测试问题");
// 验证
assertNotNull(response);
assertTrue(response.contains("测试响应"));
verify(chatModel, times(1)).call(any(Prompt.class));
}
}
小结
本章我们完成了:
- 项目初始化:使用 Spring Initializr 快速创建项目
- 依赖配置:配置 Spring AI BOM 和 Starter
- 核心代码:实现 ChatService、ChatController
- 自动配置:理解 Spring AI 的自动配置原理
- 本地模型:使用 Ollama 运行本地大模型
- 问题排查:常见问题的解决方案
练习
- 扩展对话接口:添加对话历史记录功能
- 实现流式输出:前端使用 SSE 接收流式响应
- 切换模型:尝试使用 Ollama 的不同模型
- 添加限流:使用 Spring RateLimiter 限制请求频率
下一章预告
在下一章《ChatClient API 详解》中,我们将深入探讨:
- ChatClient 的完整 API
- Prompt 模板的使用
- 多轮对话管理
- Advisor 机制详解
敬请期待!
教程系列持续更新中,欢迎关注!
相关文章
Spring AI 实战教程(九):可观测性与生产部署
2025-09-21·5 分钟阅读
全面掌握 Spring AI 应用的可观测性建设,包括监控指标、分布式追踪、日志管理,以及生产环境部署最佳实践。
Spring AI 实战教程(八):Tools 与 Function Calling
2025-09-12·5 分钟阅读
深入理解 Function Calling 原理,掌握 Spring AI Tools API,构建具备外部调用能力的智能 Agent。
Spring AI 实战教程(七):RAG 检索增强生成
2025-09-02·6 分钟阅读
深入理解 RAG 架构原理,掌握 Spring AI 的 RAG 组件,构建企业级知识库问答系统。