山东大学软件学院创新实训 易学探索助手开发记录
性能优化:修改古文句读功能和翻译功能为流式输出
一、问题说明
在实现古籍处理功能时,为进一步优化用户体验,缩短用户等待时间,我将古文句读功能和翻译功能修改为流式输出,替换了不能关闭思考功能的api,使用支持流式输出的deepseek api。
二、核心实现方案
1. 技术架构图
[前端] --(EventSource)--> [Spring Boot SSE端点] --(HTTP流)--> [Deepseek API]
2. 后端关键实现(Java)
关键点解析:
-
编码强制指定
- 请求头显式声明UTF-8
.header("Content-Type", "application/json; charset=UTF-8")- 请求体使用UTF-8编码
HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8) -
响应流处理
- 使用
ofLines()按行处理响应数据
HttpResponse.BodyHandlers.ofLines()- 过滤心跳包与结束标记
if(line.trim().isEmpty() || line.contains("[DONE]")) return; - 使用
-
SSE数据推送
- 二进制方式发送UTF-8数据
byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8); emitter.send(SseEmitter.event().data(contentBytes, MediaType.TEXT_EVENT_STREAM));
3. 前端关键实现(Vue3)
const startSse = (taskId) => {
const eventSource = new EventSource(`/api/sentenceStream/${taskId}`);
eventSource.onmessage = (event) => {
const processedContent = event.data.replace(/<br\s*\/?>/gi, '\n');
segmentedText.value += processedContent;
};
}
关键点解析:
-
换行符处理
使用正则表达式替换HTML换行标记replace(/<br\s*\/?>/gi, '\n') -
连接生命周期管理
onopen:连接建立日志onerror:异常处理onclose:状态重置
三、踩坑与解决方案
1. 中文字符乱码问题
现象:返回内容出现乱码,传送到前端的内容全部显示为问号(?)。
原因排查:
- HTTP请求未显式指定编码格式
- SSE数据传输未使用二进制方式
解决方案:
// 关键修正代码
byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
emitter.send(SseEmitter.event().data(contentBytes, MediaType.TEXT_EVENT_STREAM));
2. 流式响应中断问题
现象:长文本响应中途断开
优化方案:
- 设置
Long.MAX_VALUE超时时间
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
3. 换行符渲染问题
现象:\n在HTML中不换行
解决方案:
前端替换为<br/>后,再通过CSS控制渲染:
.white-space-pre {
white-space: pre-wrap;
}
四、总结
通过本次实践我们得出以下结论:
- 字符编码问题需要全链路统一处理
- SSE非常适合实时显示场景
- Spring Boot的
SseEmitter提供了简洁的API

浙公网安备 33010602011771号