Spring AI 学习指南(三)ChatClient 优雅调用实战
一、前言
上一节课我们深入学习了底层 ChatModel,掌握了 Message 消息、Prompt 组装、模型参数、流式输出等全套底层 API,能完整看懂 AI 调用底层流程。
在实际项目开发中,频繁手动组装消息、解析返回结果代码偏繁琐。Spring AI 提供 ChatClient 上层门面封装,采用链式编程风格,代码简洁易读、开发效率更高。
本期核心学习:ChatClient 基础用法、链式调用、角色设定、参数配置、流式对话,最后对比 ChatModel 与 ChatClient 的选用场景。
二、ChatClient 基础介绍
2.1 组件概念
ChatClient 是 Spring AI 官方推荐的上层调用客户端,基于 ChatModel 底层接口封装而来,屏蔽大量底层冗余代码,简化日常对话开发。
2.2 核心优势
- 链式调用写法,代码逻辑连贯直观
- 无需手动频繁创建 Prompt、消息集合
- 内置消息、角色、参数、流式统一调用入口
- 业务开发首选,可读性与维护性更强
2.3 与 ChatModel 简单区分
- ChatModel:底层原生接口,偏向原理学习、自定义拓展
- ChatClient:上层封装工具,偏向业务快速开发
三、ChatClient 完整实战代码
沿用现有项目环境,编写多场景接口,覆盖基础问答、角色对话、参数定制、流式输出。
pom.xml
<?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 http://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>3.5.14</version>
<relativePath/>
</parent>
<groupId>demo.ai</groupId>
<artifactId>spring-ai-demo</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.ai.version>1.1.6</spring.ai.version>
</properties>
<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>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-client-chat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-zhipuai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
application.yml
spring:
ai:
zhipuai:
api-key: 4281feecxxxxxx # 从智谱AI获取的 api-key
base-url: https://open.bigmodel.cn/api/paas
chat:
options:
model: glm-4-flash
temperature: 0.7 # 随机性 0-1 越低越严谨
server:
servlet:
# 解决流式输出乱码
encoding:
charset: UTF-8 # UTF-8字符集
force: true # 强制使用UTF-8
enabled: true # 开启 Spring Boot 内置的编码过滤器
package demo.ai.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/client")
public class ChatClientController {
private final ChatClient chatClient;
// 构造器注入ChatClient构建器
public ChatClientController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
// 1. 基础简单问答
// http://localhost:8080/client/simple?msg=介绍Spring AI
@GetMapping("/simple")
public String simpleChat(@RequestParam String msg){
return chatClient.prompt()
.user(msg)
.call()
.content();
}
// 2. 设定系统角色对话
// http://localhost:8080/client/role?msg=帮我查询内科挂号时间
@GetMapping("/role")
public String roleChat(@RequestParam String msg){
return chatClient.prompt()
.system("你是专业医院挂号助手,耐心解答挂号相关问题")
.user(msg)
.call()
.content();
}
// 3. 自定义模型参数对话
// http://localhost:8080/client/option?msg=推荐体检项目
@GetMapping("/option")
public String optionChat(@RequestParam String msg){
ZhiPuAiChatOptions chatOptions = new ZhiPuAiChatOptions();
// chatOptions.setModel("glm-4.5");
chatOptions.setTemperature(0.9);
chatOptions.setMaxTokens(1024);
return chatClient.prompt()
.system("体检咨询顾问,回答简洁实用")
.user(msg)
.options(chatOptions)
.call()
.content();
}
// 4. 流式实时输出对话
// http://localhost:8080/client/stream?msg=简述挂号基本流程
@GetMapping("/stream")
public Flux<String> streamChat(@RequestParam String msg){
return chatClient.prompt()
.system("挂号流程讲解员,分段清晰讲解")
.user(msg)
.stream()
.content();
}
}
四、接口功能逐点解析
4.1 基础问答 simple
最简链式调用,仅传入用户提问,框架自动完成消息封装与结果解析,满足日常普通聊天场景。
4.2 角色设定 role
通过 .system() 方法快速设置 AI 身份与行为规范,等同于底层 SystemMessage 效果,写法更加精简。
4.3 自定义模型参数 option
内置 options 配置项。
4.4 流式输出 stream
调用 .stream() 方法即可开启流式响应,返回 Flux 数据流,实现打字机实时展示效果,适配前端聊天页面。
五、ChatClient 与 ChatModel 对比总结
表格
| 对比项 | ChatModel | ChatClient |
|---|---|---|
| 层级位置 | 底层基础接口 | 上层封装客户端 |
| 代码风格 | 面向对象组装,代码偏多 | 链式编程,简洁优雅 |
| 消息处理 | 手动创建各类 Message | 内置方法快速传入 |
| 参数配置 | 手动实例化配置类 | 链式直接配置 |
| 适用场景 | 底层学习、自定义拓展 | 业务开发、快速上线 |
六、学习踩坑小结
1. ChatClient 依靠 Builder 构造注入,不要用 @Resource 直接注入
当然也可以使用ChatClientConfiguration,让Spring容器管理ChatClient,那么代码改造如下:
新建conf包,然后创建ChatClientConfiguration类
package demo.ai.conf;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ChatClientConfiguration {
@Bean
public ChatClient chatClient(ChatClient.Builder chatClientBuilder) {
return chatClientBuilder.build();
}
}
ChatClientController使用@Resource注解注入ChatClient
package demo.ai.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/client")
public class ChatClientController {
@Resource
private ChatClient chatClient;
// private final ChatClient chatClient;
// 构造器注入ChatClient构建器
// public ChatClientController(ChatClient.Builder chatClientBuilder) {
// this.chatClient = chatClientBuilder.build();
// }
// 1. 基础简单问答
// http://localhost:8080/client/simple?msg=介绍Spring AI
@GetMapping("/simple")
public String simpleChat(@RequestParam String msg){
return chatClient.prompt()
.user(msg)
.call()
.content();
}
// 2. 设定系统角色对话
// http://localhost:8080/client/role?msg=帮我查询内科挂号时间
@GetMapping("/role")
public String roleChat(@RequestParam String msg){
return chatClient.prompt()
.system("你是专业医院挂号助手,耐心解答挂号相关问题")
.user(msg)
.call()
.content();
}
// 3. 自定义模型参数对话
// http://localhost:8080/client/option?msg=推荐体检项目
@GetMapping("/option")
public String optionChat(@RequestParam String msg){
ZhiPuAiChatOptions chatOptions = new ZhiPuAiChatOptions();
// chatOptions.setModel("glm-4.5");
chatOptions.setTemperature(0.9);
chatOptions.setMaxTokens(1024);
return chatClient.prompt()
.system("体检咨询顾问,回答简洁实用")
.user(msg)
.options(chatOptions)
.call()
.content();
}
// 4. 流式实时输出对话
// http://localhost:8080/client/stream?msg=简述挂号基本流程
@GetMapping("/stream")
public Flux<String> streamChat(@RequestParam String msg){
return chatClient.prompt()
.system("挂号流程讲解员,分段清晰讲解")
.user(msg)
.stream()
.content();
}
}
2. 链式调用顺序:prompt() → 消息 → 参数 → 调用
3. 流式接口用浏览器查看效果最佳
4. ChatClient 底层依然是 ChatModel,只是封装更优雅
七、本篇学习收获
- 掌握 ChatClient 注入方式与链式基础语法
- 熟练实现:基础问答、角色对话、参数配置、流式输出
- 清晰分清 ChatModel 与 ChatClient 关系与使用场景
- 具备企业项目中灵活选择 API 的能力
结语
从底层 ChatModel 吃透原理,再用 ChatClient 提升开发效率,是 Spring AI 最标准的学习路径。
日常业务优先使用 ChatClient,遇到定制化需求再回到 ChatModel,就能轻松搞定企业级 AI 开发。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)