SpringBoot3 整合 SpringAI 实现ai助手(记忆)
-
- [1. 项目概述](#1. 项目概述)
- [2. 环境准备](#2. 环境准备)
-
- [2.1 安装必要软件](#2.1 安装必要软件)
- [2.2 配置环境变量](#2.2 配置环境变量)
- [3. 项目初始化](#3. 项目初始化)
-
- [3.1 创建 Spring Boot 项目](#3.1 创建 Spring Boot 项目)
- [3.2 配置 Maven 依赖](#3.2 配置 Maven 依赖)
- [4. 核心配置](#4. 核心配置)
-
- [4.1 应用配置文件 (`application.yml`)](#4.1 应用配置文件 (
application.yml)) - [4.2 Redis 配置 (`RedisConfiguration.java`)](#4.2 Redis 配置 (
RedisConfiguration.java))
- [4.1 应用配置文件 (`application.yml`)](#4.1 应用配置文件 (
- [5. 核心功能实现](#5. 核心功能实现)
-
- [5.1 创建模型类](#5.1 创建模型类)
-
- [5.1.1 创建 MessageVO.java](#5.1.1 创建 MessageVO.java)
- [5.1.2 创建 SerializableMessage.java](#5.1.2 创建 SerializableMessage.java)
- [5.2 定义仓库接口 (`ChatHistoryRepository.java`)](#5.2 定义仓库接口 (
ChatHistoryRepository.java)) - [5.3 实现 Redis 聊天历史仓库 (`RedisChatHistoryRepository.java`)](#5.3 实现 Redis 聊天历史仓库 (
RedisChatHistoryRepository.java)) - [5.4 实现聊天记忆 (`RedisChatMemory.java`)](#5.4 实现聊天记忆 (
RedisChatMemory.java)) - [5.5 配置 ChatClient (`CommonConfiguration.java`)](#5.5 配置 ChatClient (
CommonConfiguration.java)) - [5.6 实现聊天控制器 (`ChatController.java`)](#5.6 实现聊天控制器 (
ChatController.java)) - [5.7 实现聊天历史控制器 (`ChatHistoryController.java`)](#5.7 实现聊天历史控制器 (
ChatHistoryController.java))
- [6. 测试和验证](#6. 测试和验证)
-
- [6.1 启动服务](#6.1 启动服务)
- [6.2 测试聊天记忆功能](#6.2 测试聊天记忆功能)
- [6.3 测试用户隔离功能](#6.3 测试用户隔离功能)
- [6.4 测试历史记录持久化](#6.4 测试历史记录持久化)
- [6.5 测试历史记录管理](#6.5 测试历史记录管理)
1. 项目概述
本教程详细介绍如何使用 Spring Boot 3 整合 Spring AI 实现一个具有记忆功能的 AI 助手。该实现使用 Redis 作为存储介质,支持用户级别的会话隔离和 30 天的对话历史持久化。
技术栈
- Spring Boot 3.3.0
- Java 17
- Spring AI
- Redis 6.0+
- MyBatis Plus
- MySQL 8.0
- Sa-Token(用户认证)
2. 环境准备
2.1 安装必要软件
- JDK 17+:Oracle JDK 或 OpenJDK
- Maven 3.9+:Maven 官网
- Redis 6.0+:Redis 官网 或使用 Docker
- MySQL 8.0+:MySQL 官网 或使用 Docker
- IDE:IntelliJ IDEA 或 Eclipse
2.2 配置环境变量
确保 JAVA_HOME 和 MAVEN_HOME 已正确配置。
3. 项目初始化
3.1 创建 Spring Boot 项目
使用 Spring Initializr 创建项目:
- 访问 Spring Initializr
- 选择 Spring Boot 3.3.0
- 选择 Java 17
- 添加依赖:Spring Web, Spring Data Redis, MyBatis Plus, MySQL Driver, Spring Boot DevTools
3.2 配置 Maven 依赖
在 pom.xml 文件中添加以下依赖:
xml
<dependencies>
<!-- Spring Boot 核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Spring AI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
<version>1.0.0</version>
</dependency>
<!-- Sa-Token 认证 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.38.1</version>
</dependency>
<!-- Jackson 序列化 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
4. 核心配置
4.1 应用配置文件 (application.yml)
创建 src/main/resources/application.yml 文件,配置应用信息:
yaml
server:
port: 9527
servlet:
context-path: /api
spring:
application:
name: smart-pic-community-backend
# Redis 配置
data:
redis:
database: 2
host: localhost
port: 6379
timeout: 5000
# 数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/smart_pic_community
username: root
password: your_password
# Spring AI 配置
ai:
openai:
base-url: https://api.deepseek.com/ # 使用 DeepSeek API
api-key: your_api_key
chat:
options:
model: deepseek-chat
4.2 Redis 配置 (RedisConfiguration.java)
创建 Redis 配置类,确保正确序列化对象:
java
package com.spc.smartpiccommunitybackend.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@Slf4j
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
log.info("开始创建redis模板对象...");
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用 StringRedisSerializer 来序列化和反序列化 redis 的 key
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key 采用 String 的序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 redis 的 value
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// value 采用 JSON 的序列化方式
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
注意事项:
- 使用
Jackson2JsonRedisSerializer而不是StringRedisSerializer可以避免ClassCastException - 启用默认类型可以确保反序列化时能正确识别对象类型
5. 核心功能实现
5.1 创建模型类
5.1.1 创建 MessageVO.java
创建消息视图对象,用于前端展示:
java
package com.spc.smartpiccommunitybackend.model.vo.ai;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.ai.chat.messages.Message;
@NoArgsConstructor
@Data
public class MessageVO {
private String role;
private String content;
public MessageVO(Message message) {
this.role = switch (message.getMessageType()) {
case USER -> "user";
case ASSISTANT -> "assistant";
case SYSTEM -> "system";
default -> "";
};
this.content = message.getText();
}
}
功能说明:
- 将 Spring AI 的
Message对象转换为前端可识别的格式 - 根据消息类型设置不同的角色
- 提取消息内容用于展示
5.1.2 创建 SerializableMessage.java
创建可序列化的消息对象,用于 Redis 存储:
java
package com.spc.smartpiccommunitybackend.model.entity.ai;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
public class SerializableMessage implements Serializable {
private static final long serialVersionUID = 1L;
private String role;
private String content;
private String messageType;
private Long timestamp;
public SerializableMessage(String role, String content, String messageType) {
this.role = role;
this.content = content;
this.messageType = messageType;
this.timestamp = System.currentTimeMillis();
}
public SerializableMessage(String role, String content) {
this(role, content, "user");
}
}
功能说明:
- 实现
Serializable接口,支持 Redis 序列化 - 包含角色、内容、消息类型和时间戳字段
- 提供多个构造方法,方便使用
5.2 定义仓库接口 (ChatHistoryRepository.java)
创建聊天历史仓库接口:
java
package com.spc.smartpiccommunitybackend.repository;
import java.util.List;
import java.util.Map;
public interface ChatHistoryRepository {
/**
* 保存会话记录
*/
void save(String type, String chatId, Long userId);
/**
* 获取用户的会话ID列表
*/
List<String> getChatIds(Long userId, String type);
/**
* 保存聊天消息
*/
void saveMessage(String chatId, String message, String sender);
/**
* 获取聊天消息历史
*/
List<String> getMessages(String chatId);
/**
* 删除会话
*/
void deleteChat(Long userId, String type, String chatId);
/**
* 获取会话信息
*/
Map<Object, Object> getSessionInfo(String chatId);
}
5.3 实现 Redis 聊天历史仓库 (RedisChatHistoryRepository.java)
实现基于 Redis 的聊天历史仓库:
java
package com.spc.smartpiccommunitybackend.repository;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Component
@RequiredArgsConstructor
public class RedisChatHistoryRepository implements ChatHistoryRepository {
private final RedisTemplate<String, Object> redisTemplate;
// Redis key前缀
private static final String CHAT_HISTORY_PREFIX = "chat:history:";
private static final String CHAT_SESSION_PREFIX = "chat:session:";
private static final String CHAT_MESSAGES_PREFIX = "chat:messages:";
/**
* 保存会话记录
*/
@Override
public void save(String type, String chatId, Long userId) {
// 保存会话信息
String sessionKey = CHAT_SESSION_PREFIX + chatId;
Map<String, Object> sessionInfo = new HashMap<>();
sessionInfo.put("userId", String.valueOf(userId));
sessionInfo.put("type", type);
sessionInfo.put("createTime", System.currentTimeMillis());
sessionInfo.put("lastUpdateTime", System.currentTimeMillis());
redisTemplate.opsForHash().putAll(sessionKey, sessionInfo);
// 设置过期时间为30天
redisTemplate.expire(sessionKey, 30, TimeUnit.DAYS);
// 将chatId添加到用户的聊天历史列表中
String historyKey = CHAT_HISTORY_PREFIX + userId + ":" + type;
redisTemplate.opsForSet().add(historyKey, chatId);
// 设置过期时间为30天
redisTemplate.expire(historyKey, 30, TimeUnit.DAYS);
}
/**
* 获取用户的会话ID列表
*/
@Override
public List<String> getChatIds(Long userId, String type) {
String historyKey = CHAT_HISTORY_PREFIX + userId + ":" + type;
Set<Object> chatIds = redisTemplate.opsForSet().members(historyKey);
if (chatIds == null || chatIds.isEmpty()) {
return Collections.emptyList();
}
return chatIds.stream()
.map(Object::toString)
.collect(Collectors.toList());
}
/**
* 保存聊天消息
*/
@Override
public void saveMessage(String chatId, String message, String sender) {
String messagesKey = CHAT_MESSAGES_PREFIX + chatId;
// 创建消息对象
Map<String, Object> messageInfo = new HashMap<>();
messageInfo.put("content", message);
messageInfo.put("sender", sender);
messageInfo.put("timestamp", System.currentTimeMillis());
// 使用JSON格式保存消息
ObjectMapper objectMapper = new ObjectMapper();
try {
String jsonMessage = objectMapper.writeValueAsString(messageInfo);
redisTemplate.opsForList().rightPush(messagesKey, jsonMessage);
} catch (JsonProcessingException e) {
e.printStackTrace();
// 如果JSON序列化失败,使用原始消息
redisTemplate.opsForList().rightPush(messagesKey, message);
}
// 设置过期时间为30天
redisTemplate.expire(messagesKey, 30, TimeUnit.DAYS);
// 更新会话的最后更新时间
String sessionKey = CHAT_SESSION_PREFIX + chatId;
redisTemplate.opsForHash().put(sessionKey, "lastUpdateTime", System.currentTimeMillis());
// 确保会话信息也有过期时间
redisTemplate.expire(sessionKey, 30, TimeUnit.DAYS);
}
/**
* 获取聊天消息历史
*/
@Override
public List<String> getMessages(String chatId) {
String messagesKey = CHAT_MESSAGES_PREFIX + chatId;
List<Object> messages = redisTemplate.opsForList().range(messagesKey, 0, -1);
if (messages == null || messages.isEmpty()) {
return Collections.emptyList();
}
return messages.stream()
.map(Object::toString)
.collect(Collectors.toList());
}
/**
* 删除会话
*/
@Override
public void deleteChat(Long userId, String type, String chatId) {
// 从用户的聊天历史列表中删除
String historyKey = CHAT_HISTORY_PREFIX + userId + ":" + type;
redisTemplate.opsForSet().remove(historyKey, chatId);
// 删除会话信息
String sessionKey = CHAT_SESSION_PREFIX + chatId;
redisTemplate.delete(sessionKey);
// 删除聊天消息
String messagesKey = CHAT_MESSAGES_PREFIX + chatId;
redisTemplate.delete(messagesKey);
}
/**
* 获取会话信息
*/
@Override
public Map<Object, Object> getSessionInfo(String chatId) {
String sessionKey = CHAT_SESSION_PREFIX + chatId;
return redisTemplate.opsForHash().entries(sessionKey);
}
}
注意事项:
- 使用不同的 Redis key 前缀区分不同类型的数据
- 为所有 Redis 键设置过期时间,避免内存泄漏
- 处理 JSON 序列化失败的情况,提高系统健壮性
5.4 实现聊天记忆 (RedisChatMemory.java)
实现基于 Redis 的聊天记忆,支持 Spring AI 的 ChatMemory 接口:
java
package com.spc.smartpiccommunitybackend.config;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class RedisChatMemory implements ChatMemory {
private final RedisTemplate<String, Object> redisTemplate;
private static final String MEMORY_KEY_PREFIX = "chat:memory:";
private static final long EXPIRATION_DAYS = 30;
public RedisChatMemory(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public void add(String key, List<Message> messages) {
// 为特定会话添加多条消息
for (Message message : messages) {
addMessage(key, message);
}
}
@Override
public List<Message> get(String key, int maxCount) {
// 实现 get 方法,根据 key 获取消息
List<Message> messages = getMessages(key);
// 如果指定了最大数量,返回不超过该数量的消息
if (maxCount > 0 && messages.size() > maxCount) {
return messages.subList(messages.size() - maxCount, messages.size());
}
return messages;
}
@Override
public void clear() {
// 清理所有会话记忆
// 注意:这个操作会删除所有聊天记忆,谨慎使用
}
/**
* 为特定会话添加消息
*/
public void addMessage(String chatId, Message message) {
String key = MEMORY_KEY_PREFIX + chatId;
redisTemplate.opsForList().rightPush(key, message);
redisTemplate.expire(key, EXPIRATION_DAYS, TimeUnit.DAYS);
}
/**
* 获取特定会话的消息
*/
public List<Message> getMessages(String chatId) {
String key = MEMORY_KEY_PREFIX + chatId;
List<Object> objects = redisTemplate.opsForList().range(key, 0, -1);
List<Message> messages = new ArrayList<>();
if (objects != null) {
for (Object obj : objects) {
if (obj instanceof Message) {
messages.add((Message) obj);
}
}
}
return messages;
}
/**
* 清理特定会话的记忆
*/
public void clear(String chatId) {
String key = MEMORY_KEY_PREFIX + chatId;
redisTemplate.delete(key);
}
}
注意事项:
- 实现
ChatMemory接口以支持 Spring AI 的消息记忆功能 - 为每条消息设置过期时间,确保内存使用合理
- 提供批量添加和获取消息的方法,提高性能
5.5 配置 ChatClient (CommonConfiguration.java)
配置 Spring AI 的 ChatClient:
java
package com.spc.smartpiccommunitybackend.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CommonConfiguration {
@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel, ChatMemory chatMemory) {
return ChatClient.builder(openAiChatModel)
.defaultAdvisors(
new SimpleLoggerAdvisor(),
new MessageChatMemoryAdvisor(chatMemory)
)
.build();
}
}
注意事项:
- 使用
MessageChatMemoryAdvisor来启用聊天记忆功能 - 使用
SimpleLoggerAdvisor来记录聊天交互,方便调试
5.6 实现聊天控制器 (ChatController.java)
实现聊天控制器,处理 AI 对话请求:
java
package com.spc.smartpiccommunitybackend.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spc.smartpiccommunitybackend.repository.RedisChatHistoryRepository;
import com.spc.smartpiccommunitybackend.service.UserService;
import com.spc.smartpiccommunitybackend.utils.ErrorCode;
import com.spc.smartpiccommunitybackend.utils.ThrowUtils;
import com.spc.smartpiccommunitybackend.pojo.User;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.beans.factory.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
private final RedisChatHistoryRepository chatHistoryRepository;
@Resource
private UserService userService;
public ChatController(ChatClient chatClient, RedisChatHistoryRepository chatHistoryRepository) {
this.chatClient = chatClient;
this.chatHistoryRepository = chatHistoryRepository;
}
@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
public Flux<String> chat(@RequestParam(defaultValue = "讲个笑话") String prompt,
String chatId,
HttpServletRequest request) {
User loginUser = userService.getLoginUser(request);
// 校验登录用户是否为空
ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
Long userId = loginUser.getId();
// 保存会话信息
chatHistoryRepository.save("chat", chatId, userId);
// 获取历史对话消息作为上下文
List<Message> messages = new ArrayList<>();
// 添加系统消息
SystemMessage systemMessage = new SystemMessage(
"你是一个智能图片社区的AI助手,名为虹小智。请用友好、专业的语气回答用户问题," +
"提供关于图片社区的相关信息和帮助。"
);
messages.add(systemMessage);
// 获取并解析历史消息
List<String> historyMessages = chatHistoryRepository.getMessages(chatId);
ObjectMapper objectMapper = new ObjectMapper();
for (String messageStr : historyMessages) {
try {
JsonNode node = objectMapper.readTree(messageStr);
String sender = node.get("sender").asText();
String content = node.get("content").asText();
if ("user".equals(sender)) {
messages.add(new UserMessage(content));
} else if ("ai".equals(sender)) {
messages.add(new AssistantMessage(content));
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 添加用户当前消息
messages.add(new UserMessage(prompt));
// 保存用户消息到历史记录
chatHistoryRepository.saveMessage(chatId, prompt, "user");
// 调用AI模型获取响应
return chatClient.stream(messages)
.doOnNext(response -> {
// 保存AI响应到历史记录
chatHistoryRepository.saveMessage(chatId, response, "ai");
});
}
}
注意事项:
- 验证用户登录状态,确保会话隔离
- 保存用户消息和 AI 响应到历史记录
- 使用
Flux实现流式响应,提高用户体验 - 处理历史消息解析异常,提高系统健壮性
5.7 实现聊天历史控制器 (ChatHistoryController.java)
实现聊天历史控制器,处理聊天历史的获取和删除:
java
package com.spc.smartpiccommunitybackend.controller;
import com.spc.smartpiccommunitybackend.repository.RedisChatHistoryRepository;
import com.spc.smartpiccommunitybackend.service.UserService;
import com.spc.smartpiccommunitybackend.utils.ErrorCode;
import com.spc.smartpiccommunitybackend.utils.ThrowUtils;
import com.spc.smartpiccommunitybackend.pojo.User;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@RequestMapping("/ai/history")
public class ChatHistoryController {
private final RedisChatHistoryRepository chatHistoryRepository;
private final UserService userService;
public ChatHistoryController(RedisChatHistoryRepository chatHistoryRepository, UserService userService) {
this.chatHistoryRepository = chatHistoryRepository;
this.userService = userService;
}
/**
* 获取用户的聊天历史ID列表
*/
@GetMapping("/{type}")
public List<String> getChatHistory(@PathVariable String type, HttpServletRequest request) {
User loginUser = userService.getLoginUser(request);
ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
Long userId = loginUser.getId();
return chatHistoryRepository.getChatIds(userId, type);
}
/**
* 删除指定聊天历史
*/
@DeleteMapping("/{type}/{chatId}")
public boolean deleteChatHistory(@PathVariable String type,
@PathVariable String chatId,
HttpServletRequest request) {
User loginUser = userService.getLoginUser(request);
ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);
Long userId = loginUser.getId();
chatHistoryRepository.deleteChat(userId, type, chatId);
return true;
}
}
注意事项:
- 验证用户登录状态,确保只能操作自己的聊天历史
- 提供获取和删除聊天历史的接口,方便前端管理
6. 测试和验证
6.1 启动服务
- 确保 Redis 和 MySQL 服务已启动
- 运行 Spring Boot 应用
- 访问
http://localhost:9527/api/ai/chat?prompt=你好&chatId=test123测试 AI 响应
6.2 测试聊天记忆功能
- 发送第一条消息:
http://localhost:9527/api/ai/chat?prompt=你好,我叫张三&chatId=test123 - 发送第二条消息:
http://localhost:9527/api/ai/chat?prompt=你知道我叫什么名字吗?&chatId=test123 - 验证 AI 能否正确回答你的名字
6.3 测试用户隔离功能
- 使用不同用户登录
- 验证不同用户的聊天历史是否相互隔离
6.4 测试历史记录持久化
- 发送多条消息
- 重启服务
- 验证聊天历史是否仍然存在
6.5 测试历史记录管理
- 获取用户的聊天历史列表:
GET http://localhost:9527/api/ai/history/chat - 删除指定聊天历史:
DELETE http://localhost:9527/api/ai/history/chat/test123 - 验证聊天历史是否已删除