
前言在構建智能對話應用時多輪對話的上下文記憶能力是剛需。Spring AI Alibaba 提供了一套優雅的 ChatMemory 機制將對話歷史的管理、存儲和恢復過程封裝得極為簡潔。本文將帶大家從零掌握如何用 Spring AI Alibaba 集成 ChatMemory涵蓋內存存儲、Redis 持久化、流式 SSE 輸出等場景并給出可直接用于生產的配置方案。一、架構流程與核心組件整個記憶鏈路如下前端請求 → ChatClient → MessageChatMemoryAdvisor記憶攔截器↓ 自動讀取/寫入會話歷史ChatMemory消息窗口策略滑動窗口限制消息條數↓ 底層存儲ChatMemoryRepository存儲層內存/Redis/MySQL↓ 底層調用DashScopeChatModel → DashScopeApi → 阿里靈積 DashScope 平臺1. ChatMemoryRepository 存儲倉庫負責對話消息持久化存儲Spring AI Alibaba 內置三種實現InMemoryChatMemoryRepository內存存儲單機測試專用重啟丟失數據RedisChatMemoryRepositoryRedis 持久化集群/生產推薦會話自動過期支持兩種構建模式Jedis 直連、復用 Spring Redis 連接工廠JdbcChatMemoryRepository數據庫持久化長期留存對話記錄2. ChatMemory 記憶策略層標準實現MessageWindowChatMemory滑動窗口淘汰機制配置maxMessages限制最大保存消息條數自動丟棄最早對話防止上下文 Token 超限、API 計費暴漲。3. MessageChatMemoryAdvisor 記憶攔截器掛載在 ChatClient 的 Advisor 鏈路中請求前自動根據conversationId加載歷史消息模型返回后自動保存用戶/助手消息業務代碼無需手動拼接歷史。4. ConversationId 會話唯一標識不同用戶、不同聊天窗口分配獨立 ID實現會話隔離同一個 ID 自動復用歷史對話不同 ID 完全互不干擾。5. ChatModel vs ChatClient 記憶能力區分ChatModel底層原始接口無內置記憶管理能力需要手動拼接消息列表代碼冗余ChatClient上層封裝搭配 Advisor 一鍵集成 ChatMemory支持全局系統提示詞、消息自動管理、流式、函數調用企業開發首選。二、Maven 核心依賴與配置2.1 基礎依賴!-- 基礎 DashScope 對話依賴必引 --dependencygroupIdorg.springframework.ai/groupIdartifactIdspring-ai-alibaba-starter-dashscope/artifactId/dependency內存存儲無需額外依賴Redis 持久化需引入記憶擴展包并根據連接模式補充對應依賴!-- Redis記憶擴展包兩種模式都必須引入 --dependencygroupIdcom.alibaba.cloud.ai/groupIdartifactIdspring-ai-alibaba-starter-memory-redis/artifactId/dependency!-- 方式AJedis直連模式需要該依賴 --dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactId/dependency!-- 方式B復用Spring Redis連接工廠模式需要該依賴 --!--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency--2.2 application.yml 基礎配置spring:ai:dashscope:api-key: sk-xxxxxxxxxxxxxxxxxxxxchat:options:model: qwen-turbotemperature: 0.7# Redis配置Jedis直連模式通過Value讀取連接池復用模式由SpringDataRedis自動讀取data:redis:host: 127.0.0.1port: 6379password: database: 0三、方案1內存版 ChatMemory本地測試首選內存實現適用于開發調試提供兩種寫法極簡自動裝配與手動配置定制窗口大小。3.1 方式A極簡自動裝配90% 測試場景零配置類Spring AI Alibaba 自動配置了InMemoryChatMemoryRepository我們只需通過Bean定義ChatMemory和ChatClient即可無需手動創建倉庫。配置類import org.springframework.ai.chat.client.ChatClient;import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;import org.springframework.ai.chat.memory.ChatMemory;import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;import org.springframework.ai.chat.memory.MessageWindowChatMemory;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;Configurationpublic class AiMemoryConfig {// 使用自動裝配的 InMemoryChatMemoryRepositoryBeanpublic ChatMemory chatMemory(InMemoryChatMemoryRepository repository) {return MessageWindowChatMemory.builder().chatMemoryRepository(repository).maxMessages(10) // 最多保存10條消息5輪對話.build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是資深Java后端專家結合上下文簡潔回答問題).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}Controller 示例RestControllerRequestMapping(/ai/chat)public class MemoryChatController {Autowiredprivate ChatClient chatClient;Autowiredprivate ChatMemory chatMemory;/*** 同步多輪對話* param conversationId 會話ID前端生成UUID* param userMsg 用戶提問*/GetMapping(/sync)public String syncChat(RequestParam String conversationId,RequestParam String userMsg) {return chatClient.prompt().user(userMsg).advisors(spec - spec.param(ChatMemory.CONVERSATION_ID, conversationId)).call().content();}// 清空指定會話記憶DeleteMapping(/memory/clear)public String clearMemory(RequestParam String conversationId) {chatMemory.clear(conversationId);return 會話[ conversationId ]記憶已清空;}}3.2 方式B手動配置類自定義窗口上限推薦工程化寫法若需完全掌控 Bean 創建過程可手動聲明 Repository 和 ChatMemoryConfigurationpublic class AiMemoryConfig {Beanpublic InMemoryChatMemoryRepository memoryRepository() {return new InMemoryChatMemoryRepository();}Beanpublic ChatMemory chatMemory(InMemoryChatMemoryRepository repository) {return MessageWindowChatMemory.builder().chatMemoryRepository(repository).maxMessages(20) // 自定義窗口大小.build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是資深Java后端專家結合上下文簡潔回答問題).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}四、方案2Redis 持久化 ChatMemory生產環境集群推薦內存存儲致命缺陷服務重啟、多實例集群時會話記憶丟失線上必須使用 Redis 持久化。RedisChatMemoryRepository提供兩套構建方式4.1 方式AJedis 直連簡單 Demo組件內部自建 Jedis 連接不共享項目 Redis 連接池yml 配置通過Value讀取。Configurationpublic class RedisMemoryConfig {Value(${spring.data.redis.host})private String host;Value(${spring.data.redis.port})private int port;Value(${spring.data.redis.password:})private String password;Value(${spring.data.redis.database:0})private int database;Beanpublic RedisChatMemoryRepository redisChatMemoryRepository() {return RedisChatMemoryRepository.builder().host(host).port(port).password(password).database(database).build();}Beanpublic ChatMemory chatMemory(RedisChatMemoryRepository redisChatMemoryRepository) {return MessageWindowChatMemory.builder().chatMemoryRepository(redisChatMemoryRepository).maxMessages(20).build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是通義千問對話助手記住用戶全部歷史提問).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}4.2 方式B復用 Spring Data Redis 連接工廠生產推薦項目已引入spring-boot-starter-data-redis時使用連接池、哨兵、集群配置統一管理。Configurationpublic class RedisMemoryConfig {Beanpublic RedisChatMemoryRepository redisChatMemoryRepository(RedisConnectionFactory redisConnectionFactory) {return RedisChatMemoryRepository.builder().redisConnectionFactory(redisConnectionFactory).build();}Beanpublic ChatMemory chatMemory(RedisChatMemoryRepository redisChatMemoryRepository) {return MessageWindowChatMemory.builder().chatMemoryRepository(redisChatMemoryRepository).maxMessages(20).build();}Beanpublic ChatClient chatClient(ChatModel chatModel, ChatMemory chatMemory) {return ChatClient.builder(chatModel).defaultSystem(你是通義千問對話助手記住用戶全部歷史提問).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();}}Redis 記憶特性會話數據序列化存入 Redis服務重啟不丟失支持配置 Key 過期時間自動清理長期未使用會話微服務多實例集群共享 Redis多節點對話上下文統一。重要區分Jedis 直連模式內部新建獨立 Jedis 連接不和業務 Redis 共用連接池適合簡單 DemoRedisConnectionFactory 模式復用項目已有 Redis 連接池適合正式業務系統。五、流式 SSE 接口實現帶記憶打字機效果結合 ChatMemory 實現帶歷史上下文的實時流式輸出基于 WebFlux Flux SSERestControllerRequestMapping(/ai/chat)public class StreamMemoryChatController {Autowiredprivate ChatClient chatClient;/*** 流式帶記憶對話SSE實時推送*/GetMapping(value /stream, produces text/event-stream;charsetutf-8)public FluxString streamChatWithMemory(RequestParam String conversationId,RequestParam String userMsg) {return chatClient.prompt().user(userMsg).advisors(spec - spec.param(ChatMemory.CONVERSATION_ID, conversationId)).stream().content();}}六、總結與選型建議開發測試使用內存版InMemoryChatMemoryRepository極簡配置快速驗證多輪對話邏輯。單機生產內存版不持久化若可接受重啟丟失歷史也可用否則切換至 Redis 持久化。集群/微服務必須選擇Redis 持久化并推薦復用 Spring Data Redis 連接工廠實現連接池統一管理保證多實例會話共享。流式輸出只需在ChatClient基礎上調用.stream().content()即可獲得 SSE 流記憶配置無需額外改動。Spring AI Alibaba 的 ChatMemory 體系將對話上下文管理復雜度降到最低配合 ChatClient 的 Advisor 機制讓我們能更專注于業務邏輯。希望本文能幫助大家快速落地多輪對話功能如有疑問歡迎在評論區交流。