零代码革命!Spring AI + Ollama 本地模型 MCP 实战指南(附完整Demo)
1. 环境准备:零代码的起点
最近很多朋友都在问我,说看到网上那些AI应用很酷,能自动查天气、订机票、甚至帮你分析代码,但自己一上手就懵了。要么得去申请各种API,要么就得写一堆复杂的Python脚本,光是环境配置就能劝退一大半人。说实话,我刚开始也这么觉得,直到我发现了 Spring AI 和 Ollama 这两个“神器”组合。它们俩一结合,直接把本地大模型的应用开发,从“高不可攀”变成了“像写HelloWorld一样简单”。今天我就手把手带你走一遍,不用写一行核心业务代码,就能让你本地的DeepSeek或者通义千问模型,变成一个能听你指挥、帮你干活的智能助手。
那么,到底什么是“零代码”呢?这里的“零代码”不是说完全不用写任何字符,而是指你不需要去深入理解AI模型的复杂原理,也不用去处理繁琐的HTTP请求、JSON解析和函数调用逻辑。Spring AI框架已经把这些脏活累活都封装好了,你只需要做一些简单的“配置”和“声明”,就像告诉管家你需要什么服务一样。而Ollama则是那个在你电脑上默默运行、提供强大算力的“发动机”,它让你能离线运行各种开源大模型。我们的目标,就是用最省事的方法,把这两个东西连起来,实现所谓的 MCP 能力。
MCP这个词听起来挺唬人,其实你可以把它理解成AI模型的“手”和“脚”。以前AI只是个很能聊天的“大脑”,但它不知道外面世界发生了什么,也动不了你的电脑。有了MCP,AI就能调用你写好的工具函数,比如获取实时天气、查询数据库、发送邮件。这样一来,AI就从“聊天机器人”进化成了“智能助理”。而Spring AI最新版本对MCP的原生支持,正是实现这一切的关键。下面,我们就从最基础的环境搭起。
1.1 安装与启动Ollama
首先,你得有个本地模型在跑。Ollama是目前最方便的本地大模型管理工具,支持Windows、macOS和Linux。安装过程简单到令人发指。
- 前往官网下载:打开浏览器,搜索“Ollama官网”,找到对应你操作系统的安装包,直接下载安装。这步跟装个普通软件没区别。
- 拉取模型:安装完成后,打开你的终端(Windows是CMD或PowerShell,Mac是Terminal)。这里就是见证奇迹的时刻。如果你想用DeepSeek模型,就输入:
如果你想用阿里的通义千问,就输入:ollama pull deepseek-r1:8b
我实测下来,Qwen2.5-7B这个版本在普通消费级显卡(比如RTX 4060)上跑起来非常流畅,响应速度很快,智商也在线,非常适合我们做这种工具调用实验。命令执行后,它会自动下载模型文件,喝杯咖啡的功夫就好了。ollama pull qwen2.5:7b - 运行模型:模型拉取成功后,直接在终端运行:
如果看到模型开始输出对话提示符,就说明你的本地模型引擎已经成功启动了!默认情况下,Ollama的API服务会在ollama run qwen2.5:7bhttp://localhost:11434这个地址监听。记住这个地址,等下Spring AI就要来连接它。
这里有个小坑我踩过:如果你的电脑有独立显卡,Ollama默认会尝试用GPU来跑模型,这样速度飞快。如果只用CPU,虽然也能跑,但响应会慢很多。你可以在运行命令时指定,比如 ollama run qwen2.5:7b --verbose 来查看运行详情,确认是否在用GPU。
1.2 创建Spring Boot项目
模型那边准备好了,现在来准备我们的“控制中心”——Spring Boot应用。我强烈推荐使用 start.spring.io 这个网站来生成项目,这是Spring官方的一键项目生成器,能避免很多依赖冲突的破事。
-
项目配置:打开网站,在表单里填一下:
- Project: Maven (Java项目最常用的构建工具)
- Language: Java
- Spring Boot: 选择最新的稳定版(比如3.3.x)
- Group: 可以写
com.example(你的域名倒写) - Artifact: 写
ai-mcp-demo(项目名) - Dependencies: 这是关键!点击“Add Dependencies”按钮,搜索并添加以下三个:
- Spring Web: 提供Web服务能力。
- Spring AI: 这是核心,包含了AI模型连接和MCP功能。
- Lombok (可选但推荐):用注解自动生成getter/setter,让代码更简洁。
-
生成并导入:点击“Generate”按钮,会下载一个zip压缩包。解压后用你熟悉的IDE打开,比如IntelliJ IDEA 或 VS Code。IDEA会自己识别为Maven项目并开始下载依赖,稍微等一会儿就好。
到这一步,你的本地模型“发动机”和Java“控制台”都就位了。接下来,我们要用几行简单的配置,让它们两个“认亲”,互相认识并开始对话。你会发现,原来让AI调用工具,根本不需要你去写什么网络通信代码,Spring AI已经把桥都搭好了,你只需要走过去就行。
2. 核心配置:连接AI与工具
环境准备好之后,我们就进入最核心的环节:配置。以前你要想让自己写的Java服务能被AI调用,可能得设计一套复杂的API规范,还要写很多适配层代码。但现在,Spring AI引入了一个叫 ToolCallbackProvider 的概念,它就像是一个“工具注册中心”。你只需要把你写好的Java方法“注册”进去,AI模型就能自动发现、理解并调用它们。这个过程几乎是声明式的,代码量少得惊人。
2.1 配置模型连接
首先,得告诉Spring AI:“嘿,你要对话的AI大哥在哪儿”。这个配置简单到只需要一个文件。在你的 src/main/resources 目录下,找到或创建 application.properties 文件,加入下面两行:
# 告诉Spring AI,Ollama服务在哪里
spring.ai.ollama.base-url=http://localhost:11434
# 指定要使用哪个模型。这里用的是我们之前拉取的qwen2.5:7b
spring.ai.ollama.chat.model=qwen2.5:7b
第一行就是Ollama默认的API地址。第二行 spring.ai.ollama.chat.model 这个配置项是关键,它的值 qwen2.5:7b 必须和你在Ollama里拉取和运行的模型名称完全一致。如果你用的是 deepseek-r1:8b,这里也要相应修改。配置完这个,Spring Boot应用启动时,Spring AI模块就会自动去连接本地的Ollama服务,建立起一个聊天客户端。这意味着,你后面所有和AI的交互,底层都已经帮你处理好了。
2.2 创建你的第一个工具
AI模型连接上了,但它现在还是个“光杆司令”,只知道聊天,不会干活。我们来给它第一件工具。假设我们想让AI能查询天气,那我们就先创建一个“天气服务”。在项目中新建一个类,叫 WeatherService.java:
import org.springframework.stereotype.Service;
import java.time.LocalDate;
@Service // 这是一个Spring管理的服务组件
public class WeatherService {
/**
* 一个模拟的查询天气的方法。
* 在实际项目中,这里可以替换为调用真实天气API的代码。
* @param location 城市名,比如“北京”
* @param date 查询日期,格式为 yyyy-MM-dd
* @return 返回天气情况的字符串描述
*/
public String getWeather(String location, String date) {
// 这里为了演示,直接返回模拟数据
// 真实情况可以在这里集成中国天气网、和风天气等API
return String.format("【模拟数据】%s在%s的天气是:晴,温度15-25°C,微风。", location, date);
}
}
看,这就是一个再普通不过的Java方法。它接受地点和日期两个参数,返回一个字符串。我特意把它做得这么简单,就是为了说明:任何你现有的、能正常工作的Java方法,都可以几乎无成本地暴露给AI调用。你不需要为了AI而重写逻辑。
2.3 注册工具:关键的Bean定义
工具方法有了,怎么让AI知道它的存在呢?这就是Spring AI的魔法所在。我们需要创建一个配置类,或者直接在主应用类里,声明一个 ToolCallbackProvider 类型的Bean。打开项目入口类 AiMcpDemoApplication.java (名字可能根据你的项目名略有不同),修改如下:
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class AiMcpDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AiMcpDemoApplication.class, args);
}
/**
* 核心!将我们的工具服务注册给AI。
* @param weatherService Spring会自动把上面写的WeatherService注入进来
* @return 工具回调提供者
*/
@Bean
public ToolCallbackProvider toolCallbackProvider(WeatherService weatherService) {
return MethodToolCallbackProvider.builder()
.toolObjects(weatherService) // 可以传入多个工具对象
.build();
}
}
这段代码是打通任督二脉的关键。MethodToolCallbackProvider.builder() 会使用反射机制,自动扫描 weatherService 对象中的所有公共方法(比如我们的 getWeather)。然后,它会为这些方法生成一个AI能理解的“工具描述”,包括方法名、参数含义、返回值说明等。当AI模型在对话中判断需要查询天气时,它就会自动触发对这个 getWeather 方法的调用。
我实测下来,这个过程非常稳定。你不需要写任何额外的适配器或解释器。Spring AI和Ollama中的模型配合,能很好地理解自然语言中的用户意图,并映射到正确的工具和方法参数上。比如用户说“帮我看看北京明天天气”,AI会自动提取出“北京”和明天的日期,然后调用 getWeather("北京", "2024-01-01")。这一切都是自动完成的。
3. 实战演示:与你的AI助理对话
配置全部完成,是时候启动项目,看看效果了。在IDE里找到你的 AiMcpDemoApplication 类,点击运行。如果一切顺利,控制台会打印出Spring Boot的启动日志,没有报错。然后,我们怎么和这个集成了工具的AI对话呢?Spring AI为我们提供了开箱即用的HTTP端点。
3.1 使用Chat端点进行交互
Spring AI默认会暴露一个 /ai/chat 的HTTP POST接口。我们可以用任何你喜欢的工具来测试,比如 curl 命令,或者更直观的 Postman。这里我用 curl 来演示,你可以直接在终端里操作:
curl -X POST http://localhost:8080/ai/chat \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": "请问北京今天的天气怎么样?"
}
]
}'
发出这个请求后,你会看到一系列精彩的自动执行过程:
- 请求发出:你的问题被发送到Spring Boot应用。
- AI理解:Spring AI将问题转发给本地Ollama运行的Qwen2.5模型。模型会分析这句话,识别出用户的意图是“查询天气”,并提取出关键参数:
location=北京,date=今天。 - 工具调用:AI模型发现它自己有一个叫
getWeather的工具可以完成这个任务。于是它通过我们注册的ToolCallbackProvider,发起一个对WeatherService.getWeather("北京", "2024-xx-xx")的调用。 - 执行与返回:你的Java方法
getWeather被执行,返回模拟的天气字符串。 - AI组织答案:模型拿到工具返回的结果(“【模拟数据】北京在2024-xx-xx的天气是:晴...”),然后用自己的语言组织成一段通顺、友好的回复,返回给用户。
最终,你会在终端里看到类似这样的回复:
{
"message": {
"role": "assistant",
"content": "根据查询结果,北京今天(2024-xx-xx)的天气是晴天,气温在15到25摄氏度之间,有微风,是个不错的好天气。"
}
}
看到了吗?AI不仅调用了你的代码,还把返回的原始数据“翻译”成了更人性化的语言。整个过程,你作为开发者,只写了一个普通的Java方法和几行配置。你没有处理JSON解析,没有写HTTP客户端去调用模型API,更没有写复杂的逻辑去判断何时该调用哪个工具。这就是“零代码”集成的魅力——你只需要关注你的核心业务逻辑(比如 getWeather 方法里调用真实API),剩下的“智能”部分,框架和模型帮你搞定。
3.2 扩展更多工具
一个工具不过瘾?我们来给它加个“技能包”。比如,再加一个计算器功能和一个查询待办事项的功能。再创建一个 UtilityService.java:
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UtilityService {
private List<String> todoList = new ArrayList<>();
public double calculate(String expression) {
// 警告:这里仅为演示,实际项目请使用安全的表达式求值库!
// 例如使用 javax.script.ScriptEngine 或 exp4j 等。
if (expression.contains("+")) {
String[] parts = expression.split("\\+");
return Double.parseDouble(parts[0]) + Double.parseDouble(parts[1]);
}
// 简单模拟加法
return 0.0;
}
public String addTodo(String task) {
todoList.add(task);
return "已添加待办事项: " + task;
}
public List<String> getTodos() {
return new ArrayList<>(todoList); // 返回副本
}
}
然后,回到主应用类,修改 ToolCallbackProvider 的配置,把新的工具对象也加进去:
@Bean
public ToolCallbackProvider toolCallbackProvider(WeatherService weatherService, UtilityService utilityService) {
return MethodToolCallbackProvider.builder()
.toolObjects(weatherService, utilityService) // 传入多个工具对象
.build();
}
重启应用,现在你可以问更复杂的问题了:
- “帮我计算一下123加456等于多少?” -> AI会自动调用
calculate("123+456")。 - “提醒我下午三点开会。” -> AI会调用
addTodo("下午三点开会")。 - “我有哪些待办事项?” -> AI会调用
getTodos()并把列表整理成句子告诉你。
通过这个例子,你应该能深刻感受到,MCP的本质是扩展了AI的“行为能力”。它不再只是一个对话模型,而是成为了一个可以操作你业务系统、执行具体任务的智能体。而你扩展这个能力的成本,低到只是多写几个普通的业务方法而已。
4. 深入原理与最佳实践
玩转了基本功能,我们稍微深入一点,聊聊背后的原理和我踩过的一些坑,这能帮你更好地用好这个技术,避免走弯路。
4.1 Spring AI MCP 是如何工作的?
很多人好奇,Spring AI是怎么做到让AI模型“自动”调用Java方法的。其实整个过程可以分解为几个清晰的步骤,我画个简单的流程图在脑子里帮你理解:
- 请求接收:用户发送聊天请求到
/ai/chat。 - 对话历史与当前问题:Spring AI将当前用户问题和之前的对话历史(如果有)组合起来,发送给配置的AI模型(Ollama)。
- 模型推理与工具决策:这是核心。模型在生成回复时,会进行“思考”。它不仅仅在想“怎么回答”,还在判断“是否需要使用工具来回答”。如果它认为需要,就会在回复中插入一个特殊的“工具调用”请求。这个请求的格式是标准化的,包含了要调用的工具名和参数。
- 工具执行:Spring AI框架拦截到这个“工具调用”请求,根据工具名找到我们注册的对应Java方法,利用反射传入参数并执行。
- 结果回传:Java方法的执行结果被包装好,再次发送给AI模型,作为新一轮对话的“上下文”。
- 最终回复:AI模型收到工具执行结果后,结合最初的用户问题,生成最终的自然语言回复,返回给用户。
整个过程,对于模型来说,它只是在做多轮对话。对于我们的Java代码来说,它只是在响应一个普通的方法调用。Spring AI框架则充当了“翻译官”和“调度员”的角色,把两边的语言和行为统一起来。这种设计非常巧妙,它没有破坏任何一方的原有模式,只是优雅地做了适配。
4.2 我踩过的坑与避坑指南
在实际项目中用了一段时间,我总结出几个需要注意的地方,能让你事半功倍:
- 工具方法的命名与描述:AI模型理解工具的能力很强,但清晰的命名和JavaDoc注释依然非常重要。比如方法名最好用动词开头(
getWeather,calculateSum),参数名要清晰(location而不是cityName)。虽然Spring AI会自动提取方法信息,但好的命名能让模型的判断更准确。 - 参数类型要简单:尽量使用
String,Integer,Double,Boolean,List<String>这类基础或简单的类型作为工具方法的参数和返回值。复杂的自定义对象可能会让模型在参数解析时产生困惑。如果必须用复杂对象,可以考虑拆分成多个简单参数的方法。 - 错误处理:你的工具方法里一定要有健壮的错误处理。比如
getWeather里调用真实API可能会失败(网络超时、城市不存在)。当工具方法抛出异常时,Spring AI会把这个异常信息返回给AI模型,模型通常会尝试向用户解释错误。但你最好在方法内部就处理好,返回一个友好的错误信息字符串,这样用户体验更好。 - Ollama模型的选择:不是所有模型都同样擅长工具调用。像
Qwen2.5、DeepSeek-R1、Llama 3.1这些较新的模型,对工具调用的指令遵循(Instruction Following)能力都很强。而一些更早的、纯聊天优化的模型可能表现不佳。如果你发现AI总是不调用工具,或者调用参数不对,换个模型试试可能是最快的解决方案。 - 注意线程安全:我们的工具类(如
UtilityService)是Spring Singleton Bean,会被所有并发请求共享。像例子中的todoList就是一个共享状态,在真实生产环境中,你需要考虑加锁或使用线程安全的集合(如CopyOnWriteArrayList),或者更常见的,把状态持久化到数据库里。
4.3 性能与部署考量
最后,聊聊大家关心的性能和部署问题。这套方案最大的优势是“本地化”,数据不出私域,响应速度快(尤其是用GPU时),但也有些限制。
- 硬件要求:运行7B/8B参数的模型,是消费级硬件可以胜任的。8GB以上显存的显卡(如RTX 4060 Ti 16G)体验会非常好。如果只有CPU,内存建议16GB以上,响应速度会在几秒到十几秒,取决于CPU性能。对于原型验证和内部工具,这完全足够。
- Spring Boot应用部署:你的Spring Boot应用可以像任何其他Java应用一样部署。可以打包成JAR,在服务器上用
java -jar运行。需要确保部署的服务器能访问到运行Ollama的机器(localhost或内网IP)。在微服务架构下,这个AI服务可以作为一个独立的应用提供服务。 - 分离部署:更清晰的架构是将Ollama和Spring Boot应用部署在同一内网的不同机器上。Ollama部署在有GPU的机器上专职负责推理,Spring Boot应用部署在应用服务器上负责业务逻辑和工具调用。两者通过内网HTTP通信。这样能更好地利用硬件资源,也方便各自独立扩缩容。
走到这里,你已经掌握了用Spring AI和Ollama实现本地模型MCP调用的全套技能。从环境搭建、配置、编写工具到最终对话,整个过程你会发现,复杂的AI工程化问题被Spring AI这个框架大大简化了。它让Java开发者也能轻松地站在AI应用开发的前沿,而无需深陷Python生态或云API的依赖中。最让我兴奋的是,这种“零代码”集成模式,意味着你公司里现有的那些Java业务服务,都有潜力快速被赋予“智能”,从而创造出全新的用户体验和自动化流程。剩下的,就看你如何发挥想象力,把AI的能力和你熟悉的业务世界连接起来了。
更多推荐
所有评论(0)