Spring AI:Java 开发者的AI 应用开发利器

Spring AI:Java 开发者的AI 应用开发利器

在生成式 AI 席卷行业的今天,Java 开发者常常面临一个尴尬的困境:想给现有 Spring 项目集成 AI 能力,却要被迫学习 Python 生态的 LangChain、LlamaIndex,还要反复适配 OpenAI、通义千问等不同模型的 API 格式——这就像用熟悉的工具拧陌生的螺丝,效率低下且容易出错。

Spring AI 的出现,彻底改变了这一现状。作为 Spring 生态官方推出的企业级 AI 框架,它将 Spring 一贯的“抽象解耦”“开箱即用”设计哲学延伸到 AI 领域,让 Java 开发者无需切换技术栈,就能用熟悉的 Spring 风格快速构建稳定、可扩展的 AI 应用。本文将从核心认知、实战案例到企业级实践,带您全面掌握 Spring AI。

一、Spring AI 核心认知:它到底解决了什么问题?

在动手之前,我们先搞懂一个关键问题:Spring AI 不是“另一个 AI 模型”,而是“连接企业系统与 AI 模型的桥梁”。它的核心价值,就是解决 Java 开发者集成 AI 时的三大痛点:

1.1 为什么需要 Spring AI?

  • 痛点1:模型API碎片化:OpenAI 的 ChatCompletion、通义千问的 ChatCompletions、Gemini 的 GenerateContent,每个模型的 API 格式、参数名、返回结构都不同,切换模型就要重构代码。
  • 痛点2:与 Spring 生态脱节:传统 AI 框架(如 LangChain)是 Python 生态的产物,集成到 Spring Boot 项目中需要大量“胶水代码”,无法利用 Spring 的依赖注入、自动配置、安全等特性。
  • 痛点3:企业级能力缺失:生产环境需要的 API 密钥安全管理、调用监控、重试降级、向量存储集成等,传统框架要么不支持,要么需要手动实现。

Spring AI 则针对性解决这些问题:

  • 统一 API 抽象:用 ChatClient 对接所有聊天模型,EmbeddingModel 对接所有嵌入模型,切换模型只需改配置。
  • 原生 Spring 体验:支持自动配置(@EnableAutoConfiguration)、依赖注入,与 Spring Boot、Spring Cloud 无缝集成。
  • 企业级特性内置:提供可观测性(Micrometer 监控)、安全(密钥加密)、工具调用、RAG 流程编排等生产级能力。

1.2 核心组件与分层架构

Spring AI 的架构遵循“分层职责分离”原则,从下到上可分为 4 层,每一层都解决特定问题:

层级核心组件职责描述
外部服务层OpenAI/通义千问/Ollama 等实际提供 AI 能力的模型或向量数据库(如 Pinecone、Milvus)
数据支撑层VectorStore、DocumentReader处理企业数据:向量存储(存嵌入向量)、文档读取器(解析 PDF/Word)、文本分块器
模型抽象层ChatClient、EmbeddingModel统一 AI 能力接口:屏蔽不同模型的 API 差异,提供同步/流式调用能力
功能增强层PromptTemplate、RAG 编排提升 AI 效果:结构化提示、检索增强生成、工具调用(如调用企业 API)
应用层智能客服、文档问答等基于上述组件构建的业务应用

用一张简单的架构图理解:

在这里插入图片描述

1.3 与主流 AI 框架的对比

很多开发者会问:Spring AI 和 LangChain 有什么区别?下表清晰对比了核心差异:

框架语言支持Spring 集成度企业级特性适用场景
Spring AIJava★★★★★(原生)★★★★★(内置)Java 企业级 AI 应用、现有 Spring 项目升级
LangChainPython★★☆☆☆(需胶水代码)★★★☆☆(需扩展)Python 生态的 AI 原型开发、个人项目
LangChain4jJava★★★☆☆(部分支持)★★★☆☆(基础)简单 Java AI 应用,无需复杂企业特性
Dify低代码★★☆☆☆(API 对接)★★★★☆(部分)非技术人员快速搭建 AI 应用

结论:如果您是 Java 开发者,或需要将 AI 集成到 Spring 生态的企业级项目中,Spring AI 是最优选择。

二、实战上手:从 0 到 1 构建 Spring AI 应用

接下来,我们通过 3 个实战案例,从基础到进阶掌握 Spring AI:

  1. 基础案例:普通聊天(对接 OpenAI/通义千问)
  2. 进阶案例:流式聊天(实时输出,如 ChatGPT 打字效果)
  3. 企业级案例:RAG 文档问答(结合向量存储,让 AI 读你的文档)

2.1 环境准备

首先确认开发环境满足以下要求:

  • JDK 17+(Spring AI 最低要求,推荐 JDK 17)
  • Spring Boot 3.2+(需与 Spring AI 版本兼容,本文用 3.2.5)
  • Maven 3.8+ 或 Gradle 8.0+
  • 一个 AI 模型的 API 密钥(如 OpenAI API Key、通义千问 API Key)

2.2 基础案例 1:普通聊天(对接 OpenAI)

需求:构建一个 HTTP 接口,接收用户问题,返回 AI 的回答。

步骤 1:添加依赖

pom.xml 中引入 Spring AI OpenAI starter 和 Spring Web 依赖:

<<dependencies><!-- Spring AI OpenAI starter(自动配置 ChatClient) --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId><version>1.0.0-M1</version><!-- 最新稳定版可查官网 --></dependency><!-- Spring Web(提供 HTTP 接口) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> </</dependencies>
步骤 2:配置 API 密钥

src/main/resources/application.properties 中配置 OpenAI 密钥和模型:

# OpenAI API 配置 spring.ai.openai.api-key=sk-your-openai-api-key # 替换成你的密钥 spring.ai.openai.chat.model=gpt-3.5-turbo # 模型名称 spring.ai.openai.chat.temperature=0.7 # 创造性:0(严谨)~1(灵活) 
步骤 3:编写 Controller

利用 Spring AI 自动注入的 ChatClient,编写一个简单的 HTTP 接口:

importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassAIChatController{// Spring AI 自动注入 ChatClient,无需手动创建privatefinalChatClient chatClient;// 构造函数注入(Spring 推荐方式)publicAIChatController(ChatClient chatClient){this.chatClient = chatClient;}/** * 普通聊天接口:接收问题,返回 AI 回答 * 访问示例:http://localhost:8080/ai/chat?question=用Java写HelloWorld */@GetMapping("/ai/chat")publicStringchat(@RequestParamString question){// 调用 AI:链式调用,简洁明了return chatClient.prompt()// 开始构建提示.user(question)// 设置用户问题.call()// 同步调用 AI.content();// 获取回答内容}}
步骤 4:测试接口
  1. 启动 Spring Boot 应用(主类加 @SpringBootApplication 即可)。
  2. 用浏览器或 Postman 访问:http://localhost:8080/ai/chat?question=用Java写HelloWorld

预期返回:

publicclassHelloWorld{publicstaticvoidmain(String[] args){System.out.println("Hello, World!");}}
拓展:切换到国内模型(通义千问)

如果无法访问 OpenAI,只需修改依赖和配置,无需改业务代码:

  1. 重新启动,访问相同接口,即可得到通义千问的回答——这就是 Spring AI 统一 API 的魅力!

修改配置文件:

# 通义千问配置 spring.ai.tongyi.api-key=your-tongyi-api-key # 替换成你的通义千问密钥 spring.ai.tongyi.chat.model=qwen-turbo # 通义千问的模型名称 

替换依赖为通义千问 starter:

<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-tongyi-spring-boot-starter</artifactId><version>1.0.0-M1</version></dependency>

2.3 进阶案例 2:流式聊天(实时输出)

普通聊天需要等待 AI 生成完整回答后才返回,体验不佳。流式聊天则像 ChatGPT 一样,AI 生成一句就输出一句,响应更快。

Spring AI 用 响应式编程(Flux) 实现流式输出,步骤如下:

步骤 1:修改 Controller 接口

在原有 Controller 中添加流式接口,注意设置 produces = MediaType.TEXT_EVENT_STREAM_VALUE(SSE 协议,支持服务器实时推送):

importorg.springframework.http.MediaType;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importreactor.core.publisher.Flux;@RestControllerpublicclassAIChatController{// 省略已有代码.../** * 流式聊天接口:实时输出 AI 回答 * 访问示例:http://localhost:8080/ai/chat/stream?question=解释Spring Boot自动配置原理 */@GetMapping( value ="/ai/chat/stream", produces =MediaType.TEXT_EVENT_STREAM_VALUE // 启用 SSE 流式输出)publicFlux<String>streamChat(@RequestParamString question){// 关键:用 stream() 替代 call(),返回 Flux<ChatResponse>return chatClient.prompt().user(question).stream()// 开启流式调用.map(response ->{// 提取每一段生成的内容return response.getResult().getOutput().getContent();});}}
步骤 2:测试流式效果
  1. 启动应用后,用浏览器访问 http://localhost:8080/ai/chat/stream?question=解释Spring Boot自动配置原理
  2. 你会看到页面上文字“逐字逐句”出现,就像 ChatGPT 的实时输出效果。

前端集成提示:如果要在前端页面展示,只需用 JavaScript 监听 SSE 事件:

<!DOCTYPEhtml><html><body><divid="answer"></div><script>// 建立 SSE 连接const eventSource =newEventSource("http://localhost:8080/ai/chat/stream?question=解释Spring Boot自动配置原理");// 监听消息推送 eventSource.onmessage=function(event){ document.getElementById("answer").innerText += event.data;};// 监听连接关闭 eventSource.onclose=function(){ console.log("流式连接已关闭");};</script></body></html>

2.4 企业级案例 3:RAG 文档问答(让 AI 读你的文档)

普通聊天的问题是 AI 知识可能过时,且无法回答企业内部文档(如产品手册、API 文档)的问题。RAG(检索增强生成) 则通过“先检索企业文档,再让 AI 基于文档回答”,解决了这一问题。

我们以“PDF 文档问答”为例,用 Spring AI + Pinecone(向量数据库)实现 RAG:

步骤 1:核心流程理解

RAG 分为“数据准备”和“问答”两个阶段:

  1. 数据准备阶段
    • 读取 PDF 文档 → 分割成小文本块(避免超过模型上下文限制)→ 用嵌入模型生成向量 → 存储到 Pinecone。
  2. 问答阶段
    • 用户提问 → 生成问题向量 → 从 Pinecone 检索相似文本块 → 把“相似文本块+用户问题”作为提示给 AI → AI 生成基于文档的回答。
步骤 2:添加依赖

除了之前的依赖,还需引入 PDF 解析和 Pinecone 向量存储依赖:

<<dependencies><!-- 省略已有依赖... --><!-- PDF 文档解析 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-pdf-document-reader</artifactId><version>1.0.0-M1</version></dependency><!-- Pinecone 向量存储 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-pinecone-store-spring-boot-starter</artifactId><version>1.0.0-M1</version></dependency> </</dependencies>
步骤 3:配置 Pinecone

application.properties 中添加 Pinecone 配置(需先在 Pinecone 官网创建索引):

# Pinecone 配置 spring.ai.pinecone.api-key=your-pinecone-api-key # 你的 Pinecone 密钥 spring.ai.pinecone.environment=gcp-starter # Pinecone 环境(如 gcp-starter) spring.ai.pinecone.index-name=spring-ai-demo # 你的 Pinecone 索引名 # 嵌入模型配置(用 OpenAI 的嵌入模型生成向量) spring.ai.openai.embedding.model=text-embedding-3-small spring.ai.openai.embedding.dimensions=1536 # 向量维度(需与 Pinecone 索引一致) 
步骤 4:编写 RAG 服务类

创建 RagService,封装“数据准备”和“问答”逻辑:

importorg.springframework.ai.document.Document;importorg.springframework.ai.embedding.EmbeddingClient;importorg.springframework.ai.openai.OpenAiEmbeddingClient;importorg.springframework.ai.pinecone.PineconeVectorStore;importorg.springframework.ai.reader.pdf.PdfDocumentReader;importorg.springframework.ai.transformer.splitter.TextSplitter;importorg.springframework.ai.transformer.splitter.TokenTextSplitter;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.core.io.Resource;importorg.springframework.stereotype.Service;importjava.util.List;@ServicepublicclassRagService{privatefinalPineconeVectorStore vectorStore;privatefinalChatClient chatClient;privatefinalEmbeddingClient embeddingClient;// 注入 PDF 资源(将你的 PDF 放在 src/main/resources/docs/ 目录下)@Value("classpath:docs/spring-ai-manual.pdf")privateResource pdfResource;// 构造函数注入依赖publicRagService(PineconeVectorStore vectorStore,ChatClient chatClient,EmbeddingClient embeddingClient){this.vectorStore = vectorStore;this.chatClient = chatClient;this.embeddingClient = embeddingClient;}/** * 数据准备:读取 PDF → 分块 → 生成向量 → 存入 Pinecone */publicvoidprepareDocumentData(){try{// 1. 读取 PDF 文档PdfDocumentReader pdfReader =newPdfDocumentReader(pdfResource);List<Document> documents = pdfReader.read();// 2. 分割文本块(每块 500 个token,重叠 50 个token,避免语义断裂)TextSplitter textSplitter =newTokenTextSplitter(500,50);List<Document> splitDocuments = textSplitter.split(documents);// 3. 将文本块存入 Pinecone(自动生成向量) vectorStore.add(splitDocuments);System.out.println("PDF 文档处理完成,共存入 "+ splitDocuments.size()+" 个文本块");}catch(Exception e){thrownewRuntimeException("PDF 文档处理失败", e);}}/** * RAG 问答:基于 Pinecone 检索的文档回答问题 */publicStringragChat(String question){// 1. 检索相似文本块(取 top3 最相关的)List<Document> similarDocs = vectorStore.similaritySearch(question,3);// 2. 构建提示:将相似文档内容和用户问题组合String prompt =String.format(""" 基于以下文档内容回答用户问题,不要编造信息: 文档内容:%s 用户问题:%s """, similarDocs.stream().map(Document::getContent).reduce((a, b)-> a +"\n"+ b).orElse(""), question);// 3. 调用 AI 生成回答return chatClient.prompt().user(prompt).call().content();}}
步骤 5:编写 RAG 接口

在 Controller 中添加 RAG 相关接口:

importorg.springframework.web.bind.annotation.*;@RestController@RequestMapping("/ai/rag")publicclassRagController{privatefinalRagService ragService;publicRagController(RagService ragService){this.ragService = ragService;}/** * 初始化文档数据:仅需调用一次 * 访问示例:http://localhost:8080/ai/rag/init */@GetMapping("/init")publicStringinitDocument(){ ragService.prepareDocumentData();return"文档初始化完成!";}/** * RAG 问答接口:基于 PDF 文档回答问题 * 访问示例:http://localhost:8080/ai/rag/chat?question=Spring AI 如何集成向量存储 */@GetMapping("/chat")publicStringragChat(@RequestParamString question){return ragService.ragChat(question);}}
步骤 6:测试 RAG 效果
  1. 先调用初始化接口:http://localhost:8080/ai/rag/init,等待 PDF 处理完成。
  2. 再调用问答接口:http://localhost:8080/ai/rag/chat?question=Spring AI 如何集成向量存储
  3. 预期返回:AI 会基于你上传的 PDF 文档内容,准确回答问题,而不是依赖通用知识。

三、企业级实践:让 Spring AI 应用更稳定、更安全

完成基础开发后,还需要考虑生产环境的关键问题:

3.1 API 密钥安全管理

硬编码 API 密钥(如 spring.ai.openai.api-key=xxx)存在泄露风险,企业级项目建议:

  • 方式2:Spring Cloud Config 集中管理:将密钥存储在配置中心(如 Nacos、Apollo),动态刷新配置。
  • 方式3:加密存储:用 Spring Cloud Config Server + JCE 加密配置文件中的敏感信息。

方式1:环境变量注入:在服务器上设置环境变量 OPENAI_API_KEY,配置文件中引用:

spring.ai.openai.api-key=${OPENAI_API_KEY:default-key} # 冒号后是默认值(可选) 

3.2 可观测性:监控 AI 调用

Spring AI 内置了 Micrometer 监控支持,可跟踪 AI 调用的次数、响应时间、错误率:

  1. 启动后访问 http://localhost:8080/actuator/prometheus,即可看到 AI 调用的监控指标(如 spring_ai_chat_client_calls_seconds_count)。

配置监控端点:

# 暴露 Prometheus 端点 management.endpoints.web.exposure.include=prometheus,health,info management.metrics.export.prometheus.enabled=true 

添加 Actuator 依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-registry-prometheus</artifactId></dependency>

3.3 性能优化:向量缓存与批量处理

  • 向量缓存:频繁查询相同问题时,缓存检索结果(用 Redis),避免重复调用向量数据库。
  • 批量处理:若需处理大量文档,用 vectorStore.addAll() 批量添加文本块,减少网络请求次数。
  • 模型选择:非关键场景用轻量模型(如 gpt-3.5-turbo、qwen-turbo),降低延迟和成本。

四、总结:Spring AI 开启 Java 开发者的 AI 新时代

Spring AI 不是简单地“封装 AI API”,而是将 AI 能力与 Spring 生态深度融合,让 Java 开发者能以最低成本拥抱生成式 AI。它的核心价值在于:

  • 降低门槛:用熟悉的 Spring 风格开发 AI 应用,无需学习新语言或框架。
  • 提升效率:统一 API 抽象、自动配置、内置企业级特性,减少重复开发。
  • 保障稳定:支持可观测性、安全、降级,满足生产环境要求。

对于 Java 开发者而言,Spring AI 就像一把“瑞士军刀”——无论是简单的聊天功能,还是复杂的 RAG 文档问答,都能快速实现。未来,随着 Spring AI 对多模态(图像、语音)、Agent 能力的进一步增强,它将成为企业级 AI 应用开发的事实标准。

现在就动手吧:从一个简单的聊天接口开始,逐步探索 RAG、工具调用等高级特性,让你的 Spring 项目拥有智能大脑!

Read more

GLM-4.6V-Flash-WEB Web界面使用指南,拖图就出结果

GLM-4.6V-Flash-WEB Web界面使用指南,拖图就出结果 你不需要配置环境、不用写一行推理代码、甚至不用打开终端——只要把一张截图拖进浏览器窗口,几秒钟后,它就能告诉你图里写了什么、画了什么、哪里有问题。这不是未来预告,而是你现在就能在本地跑起来的真实体验。 GLM-4.6V-Flash-WEB 是智谱AI最新开源的轻量级视觉语言模型,专为Web端实时交互而生。它不像某些“实验室模型”那样只存在于论文和Benchmark表格里,而是真正做到了:部署快、启动快、响应快、上手更快。一块RTX 3090,一个浏览器,一次拖拽,结果即刻呈现。 本文不讲训练原理,不列参数表格,不堆技术术语。我们只聚焦一件事:怎么用好它的Web界面?从零开始,到稳定产出,每一步都清晰可操作。 1. 为什么说“拖图就出结果”不是宣传话术? 很多多模态模型标榜“支持图文理解”,但实际用起来才发现:要装依赖、改路径、调精度、修CUDA版本、

前端防范 XSS(跨站脚本攻击)

目录 一、防范措施 1.layui util  核心转义的特殊字符 示例 2.js-xss.js库 安装 1. Node.js 环境(npm/yarn) 2. 浏览器环境 核心 API 基础使用 1. 基础过滤(默认规则) 2. 自定义过滤规则 (1)允许特定标签 (2)允许特定属性 (3)自定义标签处理 (4)自定义属性处理 (5)转义特定字符 常见场景示例 1. 过滤用户输入的评论内容 2. 允许特定富文本标签(如富文本编辑器内容) 注意事项 更多配置 XSS(跨站脚本攻击)是一种常见的网络攻击手段,它允许攻击者将恶意脚本注入到其他用户的浏览器中。

详细教程:如何从前端查看调用接口、传参及返回结果(附带图片案例)

详细教程:如何从前端查看调用接口、传参及返回结果(附带图片案例)

目录 1. 打开浏览器开发者工具 2. 使用 Network 面板 3. 查看具体的API请求 a. Headers b. Payload c. Response d. Preview e. Timing 4. 实际操作步骤 5. 常见问题及解决方法 a. 无法看到API请求 b. 请求失败 c. 跨域问题(CORS) 作为一名后端工程师,理解前端如何调用接口、传递参数以及接收返回值是非常重要的。下面将详细介绍如何通过浏览器开发者工具(F12)查看和分析这些信息,并附带图片案例帮助你更好地理解。 1. 打开浏览器开发者工具 按下 F12 或右键点击页面选择“检查”可以打开浏览器的开发者工具。常用的浏览器如Chrome、Firefox等都内置了开发者工具。下面是我选择我的一篇文章,打开开发者工具进行演示。 2. 使用

Cursor+Codex隐藏技巧:用截图秒修前端Bug的保姆级教程(React/Chakra UI案例)

Cursor+Codex隐藏技巧:用截图秒修前端Bug的保姆级教程(React/Chakra UI案例) 前端开发中最令人头疼的莫过于那些难以定位的UI问题——元素错位、样式冲突、响应式失效...传统调试方式往往需要反复修改代码、刷新页面、检查元素。现在,通过Cursor编辑器集成的Codex功能,你可以直接用截图交互快速定位和修复这些问题。本文将带你从零开始,掌握这套革命性的调试工作流。 1. 环境准备与基础配置 在开始之前,确保你已经具备以下环境: * Cursor编辑器最新版(v2.5+) * Node.js 18.x及以上版本 * React 18项目(本文以Chakra UI 2.x为例) 首先在Cursor中安装Codex插件: 1. 点击左侧扩展图标 2. 搜索"Codex"并安装 3. 登录你的OpenAI账户(需要ChatGPT Plus订阅) 关键配置项: // 在项目根目录创建.