Java + AI 实战指南:从大模型集成到 Spring AI 落地
2026/9/8 15:49:21 网站建设 项目流程

做Java开发这么多年,我经历了从被调侃“Java不适合搞AI”,到如今Spring AI、LangChain4j这些框架把大模型能力直接塞进Spring生态的全过程。说实话,在ChatGPT刚火起来那阵,我一度觉得AI这波红利和Java没什么关系,Python社区才是绝对主场,直到自己在企业项目里真正落地了几个AI功能,才发现Java在AI领域的路线早就不是只有“调Python服务”这一条了。

这篇内容我打算把AI和Java结合这件事从头到尾捋一遍:先聊历史,再讲清楚目前被验证过的四大主流路线,最后给出一套可以直接上手的Spring AI集成实操和常见坑位排查。不管你是刚入门的Java工程师,还是正在做技术选型的高级开发,这篇文章都能帮你少走不少弯路。

1. 这十年,Java和AI的关系经历了三次大转弯

1.1 规则引擎时代:Java世界里的“伪AI”

回到十多年前,Java生态里最接近AI的东西其实是规则引擎,比如Drools、Jess这些。当时很多金融、保险、电商的风控系统,都是靠一堆if-else规则堆出来的。规则引擎把业务规则从代码里抽出来,用DRL这种专门的规则语言描述,然后通过推理引擎去匹配、执行,看起来确实有点“智能”的意思。

但严格来说,规则引擎属于专家系统的范畴,它没有学习能力,也做不了预测,所有逻辑都是人写死的。我记得很清楚,当时我们做一个信用卡反欺诈系统,规则膨胀到几千条之后,维护成本高得吓人,改一条规则要反复跑回归测试。这个阶段的“AI”本质上是知识工程,和现在大家理解的机器学习、深度学习完全是两码事。

1.2 机器学习库时代:Java的努力与尴尬

到了2010年以后,大数据和机器学习开始兴起,Java因为有Hadoop、Spark这套生态,在大数据领域占据了绝对主导地位。机器学习这块,Java也陆续出了不少库,比如Weka(怀卡托大学开发的)、Smile、Deeplearning4j(DL4J)等等。Weka在教学场景里用得挺多,图形界面点点就能跑分类聚类算法;DL4J是当时Java里少有的深度学习框架,背后有商业公司在支持,目标就是企业级部署场景。

然而很尴尬的是,Python那边的生态起飞了——scikit-learn简单好用,TensorFlow和PyTorch的出现直接把深度学习变成了Python的主场。Java这边呢,库的更新速度、社区活跃度、学习资料的丰富程度都差了一大截。那个阶段如果你在Java项目里想跑个神经网络,说实话非常痛苦,DL4J的API设计也算不上友好,踩坑只能自己去GitHub翻issue。这个时期,Java在AI领域基本处于“能跑但不好用”的尴尬状态。

1.3 大模型时代:Java重新杀回AI主战场

2022年底ChatGPT发布之后,整个AI开发的范式彻底被改变了。AI能力从“自己训练模型”变成了“调用现成的大模型API”,编程的核心从“算法实现”变成了“提示词设计、数据编排、应用集成”。这个转变对Java来说是个巨大的机会——因为大模型是远程服务,Java这边只需要发HTTP请求就能用上顶尖的AI能力,不再需要自己去实现复杂的数学运算和GPU加速。

后来事情的发展大家也看到了:Spring官方推出了Spring AI项目,LangChain4j也迅速崛起,各大云厂商都发布了Java版的SDK。我去年用Spring AI搭了一个智能客服系统,从零到上线也就花了两周,如果在几年前靠DL4J自己训练模型,这个时间根本不可能。可以说,大模型时代把Java重新拉回了AI开发的主流位置,而且这次的门槛比以前低太多。

2. 四大主流路线全景对比:先看清地图再上路

到底什么叫“AI-Java编程的主流路线”?根据我这几年在企业里的实战观察,现在基本可以归成四类,它们解决的问题、技术栈、适用场景都不一样。我先给你一张总览表,后面再逐个拆开聊。

路线核心定位典型技术栈适用场景入门门槛
路线一:经典机器学习库在Java应用内直接跑传统ML/DL算法Smile、DL4J、Weka风控评分、异常检测、小规模预测任务
路线二:大模型API集成通过SDK调用云端大模型能力Spring AI、LangChain4j、OpenAI Java SDK智能客服、文本生成、代码辅助、知识库问答
路线三:本地模型与私有化部署在自有服务器运行开源模型,Java做推理编排Ollama、llama.cpp、ONNX Runtime、vLLM数据敏感的企业内部场景、离线环境较高
路线四:AI赋能Java开发用AI工具提升Java工程师的研发效率Copilot、通义灵码、Cursor、Diffblue代码生成、单元测试、Code Review、Bug修复极低

2.1 路线一:经典机器学习库,还有没有存在价值?

许多刚接触AI的Java工程师会疑惑,既然大模型这么强,为什么还要学Smile、DL4J这些“老古董”?我的回答是:在特定场景下,它们仍然是不可替代的。

先说Smile,这个库覆盖了分类、回归、聚类、关联规则、数据预处理等几乎所有的传统机器学习算法,纯Java实现,性能和稳定性都不错。我去年做一个交易异常检测模块,训练样本是几十万条结构化数据,特征都是数值型的,这种场景用随机森林或者孤立森林就足够了,完全没必要去调大模型——又快又便宜,而且可解释性强,风控审计的时候能解释清楚“为什么判定异常”。

再说DL4J,虽然深度学习这块生态远不如PyTorch,但它在Java企业级场景有一个独特优势:可以直接嵌入JVM应用,和Spring Boot无缝集成,不需要额外维护一个Python推理服务。如果你所在的公司基础设施全是Java,不愿意为了一块模型单独引入Python技术栈,DL4J仍然是一个值得考虑的选择。

不过我要泼一盆冷水:如果你是从零开始学AI算法,我不建议从这些Java库入手。Python这边学习资源丰富得多,算法原理是一样的,你在Python里把机器学习基础搞明白,再用Smile、DL4J就是查API的事情。路线一的定位应该是“Java项目里需要嵌入算法能力”的时候用,而不是作为学习AI的起点。

2.2 路线二:Spring AI,Java开发者的最佳AI入口

如果现在你让我推荐一条最值得Java工程师学习的路线,我会毫不犹豫选路线二。原因非常简单:它最符合Java开发者已有的技能栈。

Spring AI是Spring官方在2024年正式推出的顶层项目,目标是给Java生态提供一套标准化的AI应用开发抽象。它的设计思路其实对标了Python里的LangChain,提供了一系列高层次的组件:ChatClient是对话交互的统一入口,PromptTemplate做提示词模板化,EmbeddingModel做向量化,VectorStore做向量存储,Advisor则类似于拦截器,可以在对话前后做各种处理。

我记得第一次用Spring AI的时候,最大的感受就是“太Spring了”——你熟悉的依赖注入、自动配置、Starter机制全部都用上了。在application.yml里配上api-key,创建一个ChatClient的Bean,然后像调普通Service一样调用它,就能拿到大模型的回复。这种体验让Java开发者不需要学习任何Python知识,也能快速开发AI应用。

LangChain4j则是社区驱动的另一套框架,API设计和LangChain4j更像Python版LangChain,功能上比Spring AI更激进一些,比如更早支持了AI Agent相关的特性。我的建议是:如果你在Spring Boot项目里做AI功能,优先用Spring AI,因为它毕竟是官方项目,迭代速度、社区支持都有保障;如果你需要一些Spring AI还没覆盖的高级特性,可以看看LangChain4j。

2.3 路线三:本地私有化部署,数据安全的最优解

大模型API虽然好用,但很多企业客户一听“把数据发给外部API”就摇头,尤其是金融、医疗、政务这些对数据安全极度敏感的行业。这时候就需要走路线三:把开源大模型部署在自己的服务器上,Java应用通过本地服务来调用。

本地部署的方案现在已经很成熟了。个人开发者和中小团队可以直接用Ollama,一条命令就能把Qwen2.5、Llama3.1这些开源模型跑起来,它会暴露一个兼容OpenAI格式的HTTP接口,Java这边用Spring AI的Ollama模块直接对接。如果说你的项目对并发要求比较高,或者要跑大一点的模型,可以用vLLM做推理服务,配合GPU能达到很不错的吞吐量。

这条路线我实际踩坑最多。先说硬件,跑一个7B参数的量化模型,最少需要8GB显存,如果模型更大或者上下文长度拉得很长,16GB、24GB显存也不嫌多。公司没有GPU服务器的话,只能选CPU推理方案,速度确实感人,但不失为一个预算有限时的过渡选择。另外推理服务部署好之后,Java应用和它之间的网络通信要做好超时和重试,否则模型推理慢的时候,上层接口很容易超时雪崩。

2.4 路线四:AI Agent与Java工程的深度结合

第四条路线和前面三条不太一样,它关注的不是“用Java写AI”,而是“用AI辅助写Java”。同时,随着AI Agent概念的升温,Java工程中也在出现越来越多的Agent形态应用。

先说AI辅助编程。GitHub Copilot、通义灵码、CodeGeeX这些工具对Java开发者的效率提升是实打实的。我现在的日常工作流里,写单元测试已经基本交给通义灵码了,写一个方法的同时它就能生成一套覆盖主要分支的测试代码,我再做一遍代码审查和边界情况补充就行。我们Java组在性能调优的时候,也经常让AI来分析JVM线程转储文件、堆转储文件,AI找内存泄漏、死锁问题的效率比人肉翻日志高得多。

再说Java工程里的AI Agent。这里的Agent不是简单的调用一次大模型,而是让大模型具备“感知-决策-行动”闭环:比如一个智能运维Agent,它可以接收系统指标,判断是否异常,然后自动调用告警API、生成排查报告、甚至执行恢复脚本。在Java生态里实现这类Agent,Spring AI的Advisor机制和Function Calling是很核心的技术点。Function Calling允许我们把Java方法注册给大模型,模型在回答时如果觉得需要调用某个工具,就会返回一个结构化的调用请求,Java这边执行方法后再把结果回传给模型,这样就形成了循环。

3. Spring AI集成实操:20分钟跑通你的第一个AI接口

刚才讲了那么多理论和路线,现在直接上手。这章我以Spring AI集成OpenAI兼容接口为例,从零搭建一个带流式输出的AI对话接口。之所以选这个案例而不是直接集成国内某个大模型SDK,是因为“OpenAI兼容”已经变成了事实标准,国内头部大模型厂商提供的接口也大多是兼容这个格式的,你学会通用对接方式后,切换服务商无非是改几行配置。

3.1 环境准备

先说一下我演示用的版本组合:JDK 17、Spring Boot 3.3.x、Spring AI 1.0.0。这几个版本搭配是经过验证的,Spring AI 1.0之前的Beta版本API变动比较频繁,网上很多教程写的代码拿到新版本跑不通,多半就是版本差异导致的。

项目创建方式有两种,你可以直接在Spring Initializr网站上勾选“Spring Web”和“OpenAI”这两个依赖,也可以像我一样在pom.xml里手动加。手动加的话,需要添加Spring AI的BOM来统一管理版本:

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-bom</artifactId> <version>1.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> </dependencies>

注意Spring AI的releases版本是发布在Maven中央仓库的,但如果你用的是里程碑版本(M版本)或者快照版本,需要在repositories里额外配置Spring的里程碑仓库,不然依赖会拉不下来。

3.2 配置与基础对话实现

依赖加好之后,在application.yml里设置模型服务的连接参数:

spring: ai: openai: base-url: https://api.example.com/v1 api-key: ${AI_API_KEY} chat: options: model: gpt-4o-mini temperature: 0.7

这里要重点说一下base-url这个配置,正因为国内大模型厂商大多提供OpenAI兼容接口,你可以把base-url指向任意兼容服务的地址,替换成自己申请的api-key就能用。把api-key放在环境变量而不是直接写死在配置文件里,这也是一个安全上的好习惯,防止代码上传到Git仓库的时候把密钥泄露出去。

接下来写一个最简的Controller:

@RestController @RequestMapping("/api/ai") public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder) { this.chatClient = builder.build(); } @GetMapping("/chat") public String chat(@RequestParam String message) { return chatClient.prompt(message).call().content(); } }

几行代码,一个可用的对话接口就跑起来了。启动项目,访问/api/ai/chat?message=你好,就能看到模型返回的内容。这里的ChatClient是Spring AI提供给开发者的统一对话客户端,所有底层的HTTP通信、请求构造、结果解析都被它封装掉了。你不需要关心HTTP连接池怎么配、JSON怎么序列化,这些都交给框架处理。

3.3 让你80%的场景够用的三个高级特性

第一个是Prompt模板。实际业务里,我们很少直接把用户的输入原封不动丢给模型,通常要套一个系统提示词来约束模型的角色和行为。Spring AI的PromptTemplate可以把提示词做成模板,用参数填充,代码可维护性一下子就上来了:

public String generateSummary(String content) { PromptTemplate promptTemplate = new PromptTemplate( """ 你是一个专业的文档分析师。 请阅读以下内容,并用三点总结其核心要点: {content} """ ); Message message = promptTemplate.createMessage(Map.of("content", content)); return chatClient.prompt(message).call().content(); }

第二个是流式输出。大模型生成内容需要时间,如果不做流式,用户会在接口上干等几秒甚至十几秒。有了流式输出,我们可以把SSE(Server-Sent Events)推给前端,让用户像看到打字机效果一样逐字看到回复。Spring AI把这块封装得非常好,只用把call改成stream:

@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> chatStream(@RequestParam String message) { return chatClient.prompt(message).stream().content(); }

前端用EventSource或者fetch流式接口就能直接接收,实现打字机效果只需要几行前端代码。

第三个是结构化输出。模型返回的是字符串,但业务系统里我们往往需要JSON对象,比如让模型抽取出邮件里的订单号、金额、收货地址。以前的做法是让模型“输出JSON”,然后自己写解析代码,还经常因为模型返回多余的markdown标记导致解析失败。Spring AI提供了BeanOutputConverter,可以指定一个Java类,让模型直接结构化返回:

public record OrderInfo(String orderId, BigDecimal amount, String address) {} BeanOutputConverter<OrderInfo> converter = new BeanOutputConverter<>(OrderInfo.class); String formatPrompt = converter.getFormatInstruction(); // 把formatPrompt拼到提示词里,模型就会按指定JSON结构输出 OrderInfo orderInfo = converter.convert(modelResponse);

这三个特性覆盖了我日常开发中绝大部分需求:角色扮演提示用模板,长文本生成用流式,信息抽取用结构化输出。

4. 实战RAG:让AI学会回答“你私有的知识”

纯靠大模型自身的能力,它只能回答训练数据里包含的内容,企业内部文档、产品手册、私有代码库这些它一概不知。RAG(检索增强生成)是目前解决这个问题的主流方案——先把私有文档向量化存入向量数据库,用户提问时先从库里检索出最相关的片段,再把这些片段塞进提示词让模型基于资料回答。这章我把这个流程在Java里完整跑一遍。

4.1 文档加载与文本切分

RAG的第一步是把文档转换成能检索的格式。假设我们有一些Markdown格式的产品文档,Spring AI的TikaDocumentReader可以直接读取PDF、Word、Markdown等常见格式。

文档读出来是一整块很长的文本,直接塞给模型是不行的,一方面超出上下文窗口限制,另一方面检索粒度太粗会导致命中不精准。所以要把文档切成小块,Spring AI提供了多种切分策略,我比较常用的是TokenTextSplitter:

TextSplitter splitter = new TokenTextSplitter(); List<Document> chunks = splitter.apply(reader.get());

TokenTextSplitter会按照Token数把长文档切成固定大小的片段,相邻片段之间还有一定的重叠(overlap),避免因为切断了完整句子导致检索时丢失关键信息。这个细节挺重要的——我当时图省事没设置重叠,结果很多检索结果都缺胳膊少腿,后来加上重叠之后效果立竿见影。

4.2 向量化与检索

切好的文本片段要转成向量才能做相似度检索。Spring AI的EmbeddingModel就是干这个的,同样支持OpenAI兼容接口。这里我强烈建议你根据文档语言选择Embedding模型:中文场景下用bge-large-zh这类专门优化过中文语义的模型,效果远好于通用英文Embedding模型。

向量存储这块,小项目可以直接用内存模式(SimpleVectorStore),数据量大了之后可以接Chroma、Milvus或者pgvector。生产环境我个人比较推荐pgvector——如果你所在的团队本来就用PostgreSQL,直接加一个扩展就能搞定向量存储,不需要额外运维一套新组件。

@Bean public VectorStore vectorStore(EmbeddingModel embeddingModel) { return new SimpleVectorStore(embeddingModel); } // 写入向量库 vectorStore.add(List.of(new Document("Spring AI 1.0正式版已于2024年发布..."))); // 检索相关片段 List<Document> similarDocs = vectorStore.similaritySearch( SearchRequest.query("Spring AI最新版本").withTopK(3) );

检索参数里TopK是返回最相似的几篇文档,这个值一般设置在3到5之间。太小了可能召回不全,太大了会往提示词里塞太多无关内容,反而干扰模型判断。

4.3 把RAG流程封装成服务

最后一步是把“检索-组装-生成”这一套流程串起来。Spring AI的QuestionAnswerAdvisor专门干这个事,它会在运行时自动完成向量检索,把检索到的文档插入提示词,再调用模型生成回答:

@Service public class RagService { private final ChatClient chatClient; public RagService(ChatClient.Builder builder, VectorStore vectorStore) { this.chatClient = builder .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore)) .build(); } public String ask(String question) { return chatClient.prompt(question).call().content(); } }

就这么简单,一个带私有知识库的AI问答服务就跑通了。你问“我们的产品支持哪几种部署方式”,模型不会再胡编乱造,而是基于文档内容回答,还会在回答末尾标注引用的来源,方便你回溯验证。这套流程在企业里应用的场景非常广——内部知识库问答、售后技术支持助手、研发文档检索,基本上是同一套模板套壳。

5. 实战经验汇总:那些文档里不会写的坑

5.1 模型幻觉问题,做任何AI应用都绕不开

大模型本质上是“字面接龙”,它生成的每个词都是概率预测的结果,所以它会在信息不足时一本正经地胡说八道。解决幻觉最有效的手段就是RAG,给模型提供权威资料,并且明确告诉它“如果资料里没有相关内容,直接说不知道”。如果你做的应用对准确性要求很高,可以在提示词里加一句“你只能基于以下资料回答,不得使用预训练知识”,能把很大一部分幻觉问题压下去。

5.2 Token成本控制,别让账单吓坏你老板

大模型API是按Token计费的,如果不做任何控制,生产环境分分钟跑出高额账单。我见过一个团队把对话历史全量传给模型,上下文越滚越长,单次调用成本翻了好几倍。控制成本可以从这几个维度下手:只保留最近几轮对话历史,超长的历史做摘要压缩;选择合适的模型,很多场景用mini版或轻量版完全够;给Embedding和对话模型分别设置不同的用量上限。

5.3 接口超时,分布式链路的经典问题

大模型的响应时间波动非常大,高峰期可能从正常水平飙到几十秒。如果Java应用把调用超时设得太短,高峰期就会大量报错;设得太长,上层请求堆积又会拖垮整个服务。我的实践是在Spring AI的配置里设置比较宽裕的连接超时,但在业务代码里用虚拟线程或异步方式处理,避免阻塞Servlet线程池。另外配合Spring Retry做重试时要特别小心,重试策略设置不当,等到大模型服务恢复时可能引发雪崩。

5.4 本地模型部署,资源争抢是最隐蔽的坑

如果你走了本地模型路线,JVM内存和模型推理的显存/内存争抢可能让你很头疼。一个常见场景是:Spring Boot应用默认堆内存给得很大,推理模型占用的内存也被操作系统分配出去,结果两者互相挤压导致频繁GC或者OOM。解决思路是给JVM和推理服务分别做资源限制,比如在容器里配置精准的内存limit,或者把推理服务部署到独立的GPU节点上,从物理层面隔离。另外,模型加载到显存之后,Embedding模型、重排模型、对话模型如果各占一份显存,很容易把GPU撑爆,可以考虑用共享推理框架统一部署。

6. Java工程师转型AI开发的路线选择与技能树

聊了这么多,最后一个现实的问题:作为一个Java工程师,到底怎么选路线?我的建议是分场景来看。

如果你所在的公司有数据安全红线,数据不能出内网,那就别纠结了,直接学路线三,本地部署开源模型加RAG。这条路线对Java开发者的要求主要集中在线程模型、异步编程、网络通信这些你本来就会的东西上,学习成本并不算高。而且目前Open Source模型的能力提升很快,Qwen系列在中文场景下的表现已经有接近商用闭源模型的能力。

如果你是在创业公司或者个人做产品,没有条件也没必要自建推理服务,那么路线二是最高效率的选择。它交付速度极快,尤其适合做MVP验证——上午接好API,下午就能出一个能演示的Demo。等模式验证成功了、用户量上来了,再把底层切换到私有化部署,Spring AI的抽象层让这种替换的成本保持在很低的水平。

如果你现在还处在“想学但不知道学什么”的阶段,我的建议是分两条腿走路。第一,先把Spring AI摸熟,它能帮你快速把AI能力集成到现有Spring Boot系统里;第二,补充机器学习和大模型的基础概念——Embedding、Token、Prompt、RAG、微调这些词听到你能用自己的话讲明白为止。深度学习的数学原理、反向传播这些,现阶段真的不着急,大模型时代应用开发的本质已经从“算法”转向了“工程编排”。

7. 最后再分享几个我实际用下来的经验

在做这个方向的过程中,有几个小经验想单独拎出来说一下,都是踩坑踩出来的。

第一,不要盲目追新版本。Spring AI的版本更新速度非常快,1.0之前API还在剧烈变动中,网上很多教程代码在新版本根本跑不通。我建议你绑定一个稳定版本,并且要细看官方文档中对应版本的迁移说明。我遇到过升级一个小版本,结果原来能跑的Function Calling代码要重构的尴尬情况,后来就不再追新了,稳定压倒一切。

第二,Prompt工程的能力比想象中重要。很多人觉得大模型强大到不需要在意提问方式,这是大错特错。同一道题,提示词写得好坏,答案质量天壤之别。我现在的习惯是建立一个提示词版本管理目录,每个提示词都记录当时的业务背景、调试过程、效果对比。用表格管理提示词模板,效果一目了然。你可以用结构化提示词写法:第一步描述角色,第二步交代任务背景,第三步定义输入格式,第四步明确输出格式,第五步补充边界条件和注意事项,效果稳定很多。

第三,AI Agent的落地要考虑闭环。不少人热衷于搭建复杂的Agent流程,但调试Agent和调试普通接口完全是两种体验。普通接口是确定性的输入输出,Agent则充满了不确定性,模型每一步都可能“跑偏”。我的建议是,给Agent设计好状态流转和人工介入点,在关键节点上允许人工干预和修正。生产环境的Agent没有闭环兜底机制,就是在给自己埋雷。

第四,Java团队做AI,要打破“Python优先”的思维惯性。AI应用开发和模型训练是两码事,前者是工程问题,后者是算法问题。Java工程师完全有能力做前者,而且因为本身在企业级应用有深厚的积累,做出来的东西往往更稳定、更符合工程规范。我在团队里推行AI转型时,先拿一个低风险项目(比如值班助手)练手,跑通之后再逐步扩展到核心业务,这样既验证了方案可行性,又降低了团队的挫败感。

按这几条经验走下来,Java工程师做AI开发其实没有想象中那么难。核心思路就是借力Spring AI这类框架把复杂的技术细节屏蔽掉,把精力集中在业务理解、数据准备和提示词工程上。等你的第一个AI功能上线跑起来,你会回来感谢这个时代的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询