修改 ChatController 中的 chat 和 chatStreaming 接口,将对话数据保存到 ia_messages 表中。
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | BIGINT | 主键,自增 |
| task_id | VARCHAR(64) | 任务id (Dify返回) |
| message_id | VARCHAR(64) | 信息id (Dify返回) |
| conversation_id | VARCHAR(64) | 会话id |
| app_id | VARCHAR(64) | 应用id |
| inputs | TEXT | 输入 (JSON格式) |
| query | TEXT | 问题 |
| response_mode | VARCHAR(20) | 回复模式 (blocking/streaming) |
| user_id | VARCHAR(64) | 用户id |
| answer | LONGTEXT | AI回复 |
| created_at | DATETIME | 创建时间 |
采用标准三层架构:
IaMessageEntity - 映射 ia_messages 表IaMessageMapper - 数据访问层(继承 MyBaseMapper)IaMessageService / IaMessageServiceImpl - 业务逻辑层ChatController - 在返回前调用 Service 保存数据ChatController.chat/chatStreaming
↓
调用 Dify API
↓
获取响应结果
↓
提取关键字段 → 构建 IaMessageEntity
↓
调用 IaMessageService.save()
↓
返回原结果给客户端
从 ChatDTO 获取: | ChatDTO 字段 | ia_messages 字段 | 说明 | |--------------|------------------|------| | input | inputs | List 转 JSON | | query | query | 直接映射 | | response_mode | response_mode | 直接映射 | | conversation_id | conversation_id | 直接映射 | | user | user_id | 直接映射 | | appId | app_id | 直接映射 |
从 Dify 响应获取(blocking模式):
{
"task_id": "...",
"message_id": "...",
"answer": "...",
"conversation_id": "..."
}
从 Dify 响应获取(streaming模式):
流式数据最后一帧包含完整信息,需要解析 data: 行中的 JSON。
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("ia_messages")
public class IaMessageEntity {
@TableId(type = IdType.AUTO)
private Long id;
private String taskId;
private String messageId;
private String conversationId;
private String appId;
private String inputs;
private String query;
private String responseMode;
private String userId;
private String answer;
private LocalDateTime createdAt;
}
@PostMapping("chat")
public Result<Object> chat(@RequestBody ChatDTO chatDTO) throws JsonProcessingException {
String url = difyProperties.getBaseUrl() + "chat-messages";
String body = JacksonHolder.OBJECT_MAPPER.writeValueAsString(chatDTO);
Result<Object> result = httpService.post(url, null, "Bearer "+difyProperties.getAppKeys().get(chatDTO.getAppId()), body, new TypeReference<>() {});
// 保存到数据库(异步处理,不影响主流程)
if (result.isOk() && result.getData() != null) {
saveChatMessage(chatDTO, result.getData());
}
return result;
}
流式响应需要先收集完整 answer,再保存。修改 postStream 方法或使用拦截器模式:
// 方案:修改 postStream 方法,增加回调处理最后一帧数据
httpService.postStream(url, authorization, body, emitter, (lastData) -> {
// 解析 lastData 保存到数据库
saveStreamingMessage(chatDTO, lastData);
});
| 文件类型 | 路径 | 操作 |
|---|---|---|
| Entity | storlead-knowledge-core/.../entity/IaMessageEntity.java | 新增 |
| Mapper | storlead-knowledge-biz/.../mapper/IaMessageMapper.java | 新增 |
| Service | storlead-knowledge-biz/.../service/IaMessageService.java | 新增 |
| ServiceImpl | storlead-knowledge-biz/.../service/impl/IaMessageServiceImpl.java | 新增 |
| Controller | storlead-knowledge-api/.../api/ChatController.java | 修改 |
| HttpService | storlead-knowledge-core/.../utils/HttpService.java | 修改(增加回调) |
CREATE TABLE IF NOT EXISTS `ia_messages` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`task_id` varchar(64) DEFAULT NULL COMMENT '任务id',
`message_id` varchar(64) DEFAULT NULL COMMENT '信息id',
`conversation_id` varchar(64) DEFAULT NULL COMMENT '会话id',
`app_id` varchar(64) DEFAULT NULL COMMENT '应用id',
`inputs` text COMMENT '输入(JSON)',
`query` text COMMENT '问题',
`response_mode` varchar(20) DEFAULT NULL COMMENT '回复模式',
`user_id` varchar(64) DEFAULT NULL COMMENT '用户id',
`answer` longtext COMMENT 'AI回复',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_conversation_id` (`conversation_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_app_id` (`app_id`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI对话消息记录表';