
在大语言模型(LLM)重塑软件开发的今天,Java 生态系统迎来了 Spring AI。作为 Spring 家族的最新成员,它旨在屏蔽底层 AI 模型的异构性,为开发者提供统一、标准且易于扩展的编程模型。
本文将首先深入剖析 Spring AI 的核心设计架构模式,揭示其如何通过经典的设计原则解决 AI 集成的复杂性;随后,我们将通过一个完整的实战教程,演示如何快速接入开源本地模型 Ollama,构建一个零成本、数据隐私安全的 AI 应用。
Spring AI 的设计哲学深深植根于 Spring Framework 的传统:约定优于配置、依赖注入以及面向接口编程。其架构主要围绕以下几个关键模式展开:
这是 Spring AI 的灵魂。面对 OpenAI、Azure、Anthropic、Ollama 等截然不同的 API 规范,Spring AI 定义了一套标准的领域模型(Domain Model)和核心接口。
ChatModel, EmbeddingModel, ImageModel。OpenAiChatModel, OllamaChatModel, AzureAiChatModel 等实现类。ChatModel 接口(面向接口编程)。切换模型供应商时,只需修改配置(如 application.properties 中的 spring.ai.openai.api-key 改为 spring.ai.ollama.base-url),无需改动一行 Java 代码。比如接入Ollama的实现类是org.springframework.ai.ollama.api.OllamaApi,对应标准ChatModel的实现类是org.springframework.ai.ollama.OllamaChatModel,OllamaChatModel底层实现还是需要依赖OllamaApi的。源码如下:


为了降低直接使用底层 ChatModel 的复杂度,Spring AI 引入了更高一级抽象 —— ChatClient。

设计目的: 封装 Prompt 构建、消息历史管理、异常处理等样板代码。
流畅接口: 采用链式调用风格,使代码具有极高的可读性。
示例:
String content = chatClient
.prompt("你好,你是什么大模型")
.system("作为大模型技术架构师,回答要体现技术架构思想")
.call()
.content();
AI 应用不仅仅是“问与答”,还涉及记忆、安全、日志等横切关注点。Spring AI 借鉴了 Servlet Filter 和 Spring AOP 的思想,设计了 Advisors 机制。
MessageChatMemoryAdvisor: 自动管理对话历史,实现多轮对话。PromptChatMemoryAdvisor: 优化上下文窗口。ChatClient 上。为了让 LLM 能够调用外部工具(如查询数据库、搜索网络),Spring AI 实现了双向转换机制:
针对检索增强生成(RAG),Spring AI 复用了 Spring 强大的 Resource 抽象:
DocumentSplitter 策略将长文本切分。VectorStore 接口对接 Pinecone、Milvus、PGVector 等向量数据库。这种分层设计使得构建 RAG 系统变得模块化且清晰。
Ollama 是一个流行的开源工具,允许用户在本地轻松运行 Llama 3、Qwen、Mistral 等大模型。结合 Spring AI,我们可以构建一个完全离线、数据不出域的智能应用。
确保你的机器已安装 Ollama(支持 macOS, Linux, Windows)。
默认情况下,Ollama 服务运行在 http://localhost:11434。
使用 Spring Initializr 创建项目,或使用 Maven/Gradle 初始化。
com.demodemo1Spring AI Chat Model 或直接添加依赖)在 pom.xml 中添加 Spring AI Ollama 启动器。(注:请根据最新的 Spring AI 版本调整版本号,当前推荐使用2.0.0-M2或更高版本)
<?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>4.0.3</version>
<relativePath/><!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>demo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo1</name>
<description>demo1</description>
<properties>
<java.version>25</java.version>
<spring-ai.version>2.0.0-M2</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-jsoup-document-reader</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-markdown-document-reader</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-pdf-document-reader</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-starter-model-chat-memory</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-starter-model-chat-memory-repository-redis</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-starter-model-openai</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.ai</groupId>-->
<!-- <artifactId>spring-ai-starter-model-openai-sdk</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<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>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.properties)配置 Ollama 的基础 URL 和默认模型名称(ollama需求提前下载qwen3:4b模型)。
spring.application.name=demo1
spring.ai.ollama.base-url=http://localhost:11434
spring.ai.ollama.chat.options.model=qwen3:4b
利用 ChatClient 进行交互。这里我们演示一个简单的演示。
@Configuration
publicclass ChatConfig implements SmartLifecycle {
private ChatClient chatClient;
@Bean
public ChatClient openAiChatClient(ChatClient.Builder builder) {
chatClient = builder.build();
return chatClient;
}
@Override
public void start() {
new Thread(() -> {
System.out.println("==================");
System.out.println("==================");
System.out.println("开始聊天:你好,你是什么大模型");
// String content = chatClient
// .prompt("你好,你是什么大模型")
// .system("作为大模型技术架构师,回答要体现技术架构思想")
// .call()
// .content();
//
// System.out.println(content);
Flux<String> stringFlux = chatClient
.prompt("你好,你是什么大模型")
.system("作为大模型技术架构师,回答要体现技术架构思想")
.stream().content();
stringFlux.subscribe(System.out::print);
System.out.println("==================");
System.out.println("==================");
}).start();
}
@Override
public void stop() {
}
@Override
public boolean isRunning() {
returnfalse;
}
}
Demo1Application.java。
通过这个 Ollama 实战案例,我们可以清晰地看到 Spring AI 架构模式的实际价值:
llama3.2 切换到云端的 OpenAI GPT-4,你只需要:pom.xml 依赖(引入 spring-ai-openai-spring-boot-starter)。application.yml(配置 API Key 和 URL)。@Tool 注解,Spring AI 的转换器模式会自动让 Ollama 模型学会调用这个搜索工具,无需手动编写 Prompt 解析逻辑。Advisor 来记录所有的输入输出日志,或者限制最大 Token 消耗,为未来生产环境打下坚实基础。Spring AI 通过精妙的架构设计,将复杂的 AI 集成工作简化为标准的 Spring 开发体验。它不仅提供了统一的抽象层来应对多变的模型市场,更通过丰富的扩展点满足了企业级应用的需求。
配合 Ollama 这样的本地推理引擎,Java 开发者现在可以低成本、高隐私地在本地构建和迭代 AI 应用,并在准备好时无缝迁移至云端高性能模型。这正是 Spring AI “一次编写,到处运行”理念在 AI 时代的完美延续。