一个完整的类 ChatGPT 对话系统,支持流式输出、打断,会话历史,前后端分离架构,非常适合拿来练手熟悉技术实现或者面试使用,接上一篇前端
基于 Spring Boot 2.7.18 + MyBatis-Plus + JWT 的 AI 对话系统后端服务。
技术栈
- Spring Boot 2.7.18 - 核心框架
- MyBatis-Plus 3.5.5 - ORM 框架
- JWT - 身份认证
- MySQL 8.0 - 数据存储
- DeepSeek API - AI 对话能力
- Knife4j - API 文档
核心功能
1. 用户认证体系
采用 JWT Token 实现无状态认证:
// JwtUtil.java - Token 生成与验证
@Component
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
public String generateToken(Long userId, String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(String.valueOf(userId))
.claim("username", username)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
}
2. 用户级 API Key 管理
每个用户独立绑定自己的 DeepSeek API Key,存储于 user.api_key 字段:
// UserServiceImpl.java - 注册时保存用户 API Key
@Override
@Transactional
public void register(RegisterRequest request) {
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setApiKey(request.getApiKey()); // 用户专属 API Key
user.setStatus(1);
save(user);
}
3. 流式对话实现
通过 SSE (Server-Sent Events) 实现流式响应:
// AiChatServiceImpl.java - 流式对话核心逻辑
@Override
public void streamChat(ChatRequest request, Long userId, HttpServletResponse response) {
// 1. 从用户获取 API Key
User user = userService.getById(userId);
String apiKey = user.getApiKey();
// 2. 设置 SSE 响应头
response.setContentType("text/event-stream");
response.setCharacterEncoding("UTF-8");
// 3. 调用 DeepSeek API
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "Bearer " + apiKey);
// 4. 流式转发响应
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line + "\n");
writer.flush();
// 解析内容保存到数据库
if (line.startsWith("data: ") && !line.equals("data: [DONE]")) {
parseAndSaveContent(line, aiMessage);
}
}
}
}
4. 会话与消息管理
- 会话表 (
chat_session): 存储对话元数据 - 消息表 (
chat_message): 存储对话内容,支持reasoning_content深度思考
5. 打断功能实现
前端通过 AbortController 中断请求,后端检测连接状态:
// 检测客户端是否断开连接
private boolean isClientConnected(HttpServletResponse response, PrintWriter writer) {
try {
writer.write("");
writer.flush();
return !writer.checkError();
} catch (Exception e) {
return false;
}
}
项目结构
src/main/java/com/webseek/
├── common/ # 通用工具类
│ ├── JwtUtil.java
│ ├── CurrentUser.java
│ └── Result.java
├── config/ # 配置类
│ ├── WebConfig.java
│ └── JwtInterceptor.java
├── controller/ # 控制器层
│ ├── AuthController.java
│ ├── ChatController.java
│ ├── SessionController.java
│ └── UserController.java
├── service/ # 服务层
│ ├── AiChatService.java
│ ├── UserService.java
│ └── impl/
├── entity/ # 实体类
│ ├── User.java
│ ├── ChatSession.java
│ └── ChatMessage.java
├── dto/ # 数据传输对象
│ ├── request/
│ └── response/
└── mapper/ # MyBatis Mapper
数据库表结构
-- 用户表
CREATE TABLE `user` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL UNIQUE,
`password` VARCHAR(100) NOT NULL,
`nickname` VARCHAR(50),
`api_key` VARCHAR(500), -- DeepSeek API Key
`status` TINYINT DEFAULT 1,
`deleted` TINYINT DEFAULT 0,
`create_time` DATETIME,
`update_time` DATETIME
);
-- 会话表
CREATE TABLE `chat_session` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`session_id` VARCHAR(64) NOT NULL UNIQUE,
`user_id` BIGINT NOT NULL,
`title` VARCHAR(200) DEFAULT '新对话',
`model` VARCHAR(50),
`deleted` TINYINT DEFAULT 0,
`create_time` DATETIME,
`update_time` DATETIME
);
-- 消息表
CREATE TABLE `chat_message` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`message_id` VARCHAR(64) NOT NULL UNIQUE,
`session_id` VARCHAR(64) NOT NULL,
`user_id` BIGINT NOT NULL,
`role` VARCHAR(20) NOT NULL, -- user/assistant
`content` TEXT,
`reasoning_content` TEXT, -- 深度思考内容
`deleted` TINYINT DEFAULT 0,
`create_time` DATETIME
);
配置说明
修改 application.yml 中的数据库配置:
spring:
datasource:
url: jdbc:mysql://your-host:3306/webseek?useUnicode=true&characterEncoding=utf-8
username: your-username
password: your-password
启动方式
# 开发环境
mvn spring-boot:run
# 打包
mvn clean package
# 运行
java -jar target/webseek-backend-1.0.0.jar
API 文档
启动后访问:http://localhost:8090/doc.html
核心设计亮点
- 用户级 API Key: 每个用户独立配置,安全隔离
- 流式响应: SSE 实现打字机效果,支持实时打断
- JWT 认证: 无状态设计,支持水平扩展
- 逻辑删除: MyBatis-Plus 自动处理软删除
- 深度思考: 支持 DeepSeek-R1 推理模型
源码地址[gitee.com/SongTaoo/re…]