不知不觉已经2个多月,感谢各位朋友的认可和支持!
随着AI的日新月异,很多公司都开展了AI相关的业务,这也使得很多公司的老板都想去沾沾边,而他却不知道自己公司的项目即屎山代码还是老的架构,所以很多朋友问:“老项目呢?大量Spring 4/Spring Boot 1.x的核心系统,想做AI但新框架都用不了,升级风险又大”
这个问题问得太真实了。不少公司的核心系统还跑在Spring Framework 4.x / Spring Boot 1.x上,想做大模型功能,但一查文档就懵了——Spring AI要求Spring Boot 3.x,LangChain4j的Spring Boot集成也要2.7起步,直接引入全是javax.*和jakarta.*的冲突,编译都过不了。
这个问题问得太真实了。很多公司的核心系统还跑在Spring Framework 4.x / Spring Boot 1.x上,想做大模型功能,但一查文档就懵了——Spring AI要求Spring Boot 3.x,LangChain4j的Spring Boot集成也要2.7起步,直接引入全是javax.*和jakarta.*的冲突,编译都过不了。
升级框架?那可是核心业务系统,回归测试跑一遍半个月,出了事故谁背锅?
但Spring 4就真的没法做AI了吗?当然不是。大模型本质上就是个HTTP接口,和你调第三方支付、调短信网关没有任何区别。今天给3种方案,从最简单的零依赖手写调用,到官方SDK,再到微服务拆分,不用升级一行Spring代码,Spring 4项目也能接入大模型。
先搞清楚:为什么新框架在Spring 4里用不了?
很多人以为是版本太低,其实核心原因是Java EE和Jakarta EE的不兼容。
- Spring 4 / Spring Boot 1.x → 用的是Java EE,包名是
javax.servlet.*、javax.persistence.* - Spring Boot 3.x / Spring 6 → 用的是Jakarta EE,包名是
jakarta.servlet.*、jakarta.persistence.*
这两个包名不兼容,所以Spring AI、LangChain4j的Spring Boot Starter这些基于Spring Boot 3的框架,直接在Spring 4项目里引入就会报类冲突。但注意:不兼容的是"Spring集成层",不是"大模型调用本身"。只要不用那些Spring Boot Starter,纯Java的大模型调用在任何Spring版本里都能跑。
理解了这一点,下面3种方案就顺理成章了。
方案1:OkHttp手写调用大模型API(零依赖,首选)
这是最简单、最通用、最不容易出问题的方案。大模型的接口就是标准的HTTP POST,返回JSON,你用OkHttp发请求、用fastjson解析响应,完事。
优点:零Spring依赖,JDK 6+就能跑,不侵入现有项目,不会有任何依赖冲突
缺点:需要自己封装重试、超时、流式输出(但这些都不难)
第一步:引入依赖(Spring 4兼容版本)
注意版本选择,不要用最新版,最新版可能要求高版本JDK:
<!-- OkHttp 3.12.x是最后一个支持JDK 7的版本,JDK 8用3.14.x也没问题 --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.14.9</version> </dependency> <!-- fastjson 1.2.x,兼容低版本JDK,不要用fastjson2 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency>第二步:封装大模型客户端
package com.example.ai; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import okhttp3.*; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; /** * 大模型通用客户端(Spring 4兼容,零Spring依赖) * 基于通义千问OpenAI兼容接口,其他模型改base-url即可 */ public class LlmClient { private final OkHttpClient httpClient; private final String apiKey; private final String baseUrl; private final String model; public LlmClient(String apiKey, String baseUrl, String model) { this.apiKey = apiKey; this.baseUrl = baseUrl; this.model = model; this.httpClient = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build(); } /** * 最简对话调用 * @param systemPrompt 系统提示词 * @param userMessage 用户问题 * @return 大模型回答 */ public String chat(String systemPrompt, String userMessage) throws IOException { // 1. 构建消息 JSONObject systemMsg = new JSONObject(); systemMsg.put("role", "system"); systemMsg.put("content", systemPrompt); JSONObject userMsg = new JSONObject(); userMsg.put("role", "user"); userMsg.put("content", userMessage); JSONArray messages = new JSONArray(); messages.addAll(Arrays.asList(systemMsg, userMsg)); // 2. 构建请求体 JSONObject requestBody = new JSONObject(); requestBody.put("model", model); requestBody.put("messages", messages); requestBody.put("temperature", 0.3); // 3. 发送HTTP请求 Request request = new Request.Builder() .url(baseUrl + "/chat/completions") .addHeader("Authorization", "Bearer " + apiKey) .addHeader("Content-Type", "application/json") .post(RequestBody.create( MediaType.parse("application/json; charset=utf-8"), requestBody.toJSONString())) .build(); // 4. 解析响应 try (Response response = httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("大模型调用失败,HTTP状态码:" + response.code() + ",响应:" + response.body().string()); } String body = response.body().string(); JSONObject json = JSON.parseObject(body); return json.getJSONArray("choices") .getJSONObject(0) .getJSONObject("message") .getString("content"); } } /** * 带重试的调用(生产环境必备) */ public String chatWithRetry(String systemPrompt, String userMessage, int maxRetries) { for (int i = 0; i < maxRetries; i++) { try { return chat(systemPrompt, userMessage); } catch (IOException e) { System.err.println("第" + (i + 1) + "次调用失败:" + e.getMessage()); if (i == maxRetries - 1) { throw new RuntimeException("大模型调用失败,已重试" + maxRetries + "次", e); } try { Thread.sleep(1000 * (i + 1)); // 指数退避 } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } } return null; } }第三步:在Spring 4项目里使用
package com.example.service; import com.example.ai.LlmClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.io.IOException; /** * 在Spring 4项目中使用大模型 * 注意:这里用的是javax.annotation.PostConstruct(Java EE), * 不是jakarta.annotation.PostConstruct(Jakarta EE) */ @Service public class AiService { @Value("${llm.api-key}") private String apiKey; @Value("${llm.base-url:[https://dashscope.aliyuncs.com/compatible-mode/v1](https://dashscope.aliyuncs.com/compatible-mode/v1)}") private String baseUrl; @Value("${llm.model:qwen-turbo}") private String model; private LlmClient llmClient; @PostConstruct public void init() { // 手动new出来,不需要Spring Boot Starter自动装配 this.llmClient = new LlmClient(apiKey, baseUrl, model); } /** * 智能问答 */ public String ask(String question) { try { String systemPrompt = "你是一个 helpful 的智能助手,回答要简洁准确。"; return llmClient.chatWithRetry(systemPrompt, question, 3); } catch (Exception e) { // 降级兜底:大模型不可用时返回默认回答 return "抱歉,AI服务暂时不可用,请稍后重试。"; } } }关键点:整个客户端没有任何Spring依赖,就是纯Java + OkHttp + fastjson。你把
LlmClient这个类复制到任何Spring 4、Spring 3、甚至纯Servlet项目里,都能直接用。这是最稳妥的方案,没有之一。
方案2:引入官方SDK,不依赖Spring版本
如果你不想自己封装HTTP调用,可以用大模型厂商的官方SDK。这些SDK通常是纯Java库,不依赖Spring,所以在Spring 4项目里也能直接引入。
以阿里通义千问的官方SDK为例:
第一步:引入依赖
<!-- 通义千问官方SDK,纯Java库,不依赖Spring --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dashscope-sdk-java</artifactId> <version>2.14.6</version> <!-- 选兼容JDK 8的版本,不要用最新版 --> </dependency>第二步:使用SDK调用
package com.example.ai; import com.alibaba.dashscope.aigc.generation.Generation; import com.alibaba.dashscope.aigc.generation.GenerationParam; import com.alibaba.dashscope.aigc.generation.GenerationResult; import com.alibaba.dashscope.common.Message; import com.alibaba.dashscope.common.Role; import java.util.Arrays; /** * 使用官方SDK调用大模型(不依赖Spring) */ public class DashScopeService { private final String apiKey; public DashScopeService(String apiKey) { this.apiKey = apiKey; } public String chat(String userMessage) throws Exception { // 1. 构建消息 Message systemMsg = Message.builder() .role(Role.SYSTEM.getValue()) .content("你是一个 helpful 的助手。") .build(); Message userMsg = Message.builder() .role(Role.USER.getValue()) .content(userMessage) .build(); // 2. 构建请求参数 GenerationParam param = GenerationParam.builder() .apiKey(apiKey) .model("qwen-turbo") .messages(Arrays.asList(systemMsg, userMsg)) .temperature(0.3f) .build(); // 3. 调用 Generation gen = new Generation(); GenerationResult result = gen.call(param); // 4. 解析结果 return result.getOutput().getChoices().get(0).getMessage().getContent(); } }优点:官方维护,功能全(支持流式、Function Calling、多模态等),不用自己封装HTTP
缺点:
- 引入额外依赖,老项目可能和现有依赖冲突(比如okhttp版本、gson版本)
- SDK版本更新快,新版本可能要求高版本JDK,一定要选兼容你JDK版本的旧版本
- 绑定特定厂商,换大模型要改代码
避坑提醒:引入官方SDK前,先看它的依赖树。很多SDK内部依赖了okhttp、gson、guava等,如果你的项目里已经有这些库且版本不同,很容易出现
NoSuchMethodError。冲突了就用maven的exclusions排掉,或者干脆回方案1自己手写。
方案3:单独起AI微服务,老项目HTTP/RPC调用(长期推荐)
如果你的AI功能会越来越复杂(要做RAG、Agent、多轮对话、流式输出),方案1和2就不够用了——你会想要Spring AI、LangChain4j这些完整框架的能力,但又不想动老项目。
这时候最佳方案是:新起一个独立的AI微服务,用最新的Spring Boot 3 + LangChain4j,老项目通过HTTP或RPC调用它。
架构图
┌─────────────────────┐ HTTP/Feign ┌─────────────────────┐ │ 老项目(Spring 4)│ ───────────────────> │ AI微服务(Spring Boot 3)│ │ 业务逻辑/数据库 │ │ LangChain4j / RAG / Agent │ │ 现有功能不变 │ <─────────────────── │ 大模型调用 / 向量检索 │ └─────────────────────┘ JSON响应 └─────────────────────┘老项目侧调用代码(Feign,Spring 4兼容)
package com.example.ai; import feign.Headers; import feign.Param; import feign.RequestLine; /** * Feign客户端调用AI微服务(Spring 4兼容,用feign-core即可) */ public interface AiServiceClient { @RequestLine("POST /api/ai/chat") @Headers("Content-Type: application/json") String chat(ChatRequest request); class ChatRequest { private String question; private String userId; // getter/setter省略 public String getQuestion() { return question; } public void setQuestion(String question) { this.question = question; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } } }// 在Spring 4项目中配置Feign客户端 package com.example.config; import com.example.ai.AiServiceClient; import feign.Feign; import feign.jackson.JacksonDecoder; import feign.jackson.JacksonEncoder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AiServiceConfig { @Value("${ai.service.url:[http://localhost:8081](http://localhost:8081)}") private String aiServiceUrl; @Bean public AiServiceClient aiServiceClient() { return Feign.builder() .encoder(new JacksonEncoder()) .decoder(new JacksonDecoder()) .target(AiServiceClient.class, aiServiceUrl); } }优点:
- AI能力独立演进,新技术随便用(Spring Boot 3、LangChain4j、流式输出、RAG全上)
- 不影响老项目,老项目代码几乎不用改
- 独立部署、独立扩容、独立监控,AI服务挂了不影响核心业务
- 多个老项目可以共用一个AI微服务
缺点:
- 多一个服务要运维(但现在容器化部署很简单)
- 有网络开销(内网调用延迟很低,可忽略)
- 需要处理服务发现、鉴权等微服务基础问题
核心判断:如果只是简单调大模型问答,方案1就够了;如果AI功能会持续迭代、越来越复杂,直接上方案3,一劳永逸。
三种方案对比
| 维度 | 方案1:OkHttp手写 | 方案2:官方SDK | 方案3:微服务拆分 |
|---|---|---|---|
| 依赖侵入性 | 极低(仅OkHttp+fastjson) | 中(SDK+传递依赖) | 老项目零侵入 |
| 改造成本 | 最低(复制一个类) | 低(引入依赖+调用) | 中(新起服务+接口对接) |
| 功能完整度 | 基础(需自己扩展) | 高(官方全功能) | 最高(任何框架都能用) |
| 维护成本 | 低(自己控制代码) | 中(跟SDK版本升级) | 中(多一个服务) |
| 依赖冲突风险 | 几乎为零 | 有(需排查传递依赖) | 零 |
| 适用场景 | 简单问答、快速接入 | 需要官方高级功能 | AI功能复杂、长期迭代 |
我的选型建议
- 你只是想给老项目加个智能问答/文案生成功能?→ 方案1,OkHttp手写,半小时搞定,最稳妥
- 你需要流式输出、Function Calling等高级功能,又不想起新服务?→ 方案2,官方SDK,注意选兼容版本
- 你要做完整的RAG/Agent系统,AI功能会持续迭代?→ 方案3,微服务拆分,长期来看最省心
- 你的项目JDK版本特别低(JDK 6/7)?→ 方案1,选OkHttp 3.12.x + fastjson 1.2.x,这是唯一能跑的方案
最后说一句:不要被"新框架必须高版本Spring"吓住。大模型的本质就是HTTP接口,只要能发HTTP请求,任何Java项目都能做AI。先从方案1跑通最小闭环,看到效果再决定要不要升级,这才是老项目做AI的正确姿势。
📦 落地资源推荐
AI应用框架开发需要稳定的测试环境,我平时调试框架、跑RAG验证都用阿里云轻量应用服务器,2核4G跑SpringBoot + 大模型调用完全够用,新用户首年特惠性价比很高再加上现在可以领取的9折券,适合自己动手搭一个AI测试环境。有部署需求的朋友,可以点击查看https://www.aliyun.com/daily-act/ecs/activity_selection?userCode=fzoabro9阿里云开发者特惠活动,无需求直接忽略即可。
💡 领取完整源码
关注图片上水印即Java-AI工程师,后台回复【选型】,领取本文完整源码,含 OkHttp 手写客户端(带重试降级)、DashScope SDK 调用示例、Feign 微服务调用示例、Spring 4 兼容版本 pom.xml,复制到项目直接运行。
📢 下期预告
选型踩坑是Java开发者的普遍痛点,很多人为了技术而技术,盲目上框架,最后发现不匹配,重构成本极高。所以我们下一篇讲:Java AI 框架选型最容易踩的 5 个坑:90% 的人至少中 2 个
本文属于「Java AI工具选型」合集