不写前端代码,curl直接调试sse、postman调试sse
和前端准备对接一个SSE(Server-Sent Events)服务器推送事件 接口,作为后端开发,之前也没对接过这类接口,在没有前端页面时不知道咋自测,后面发现直接在idea内开两个终端Terminal窗口curl就能完成自测了,不用手写一个前端页面。用postman自测也行,文末会讲。
文章目录
一、后端代码(Java)
1. 接口拆分
分为三个接口:连接、发送信息、断开连接
过程如下:
客户端向服务端发送建立连接请求;
服务端向客户端推送内容;
服务端向客户端发送结束信号并结束
2.注意事项
请求头和响应体要设置一些属性值。
响应头:
设置content-type为text/event-stream,
设置transfer-encoding为chunked;
请求头:
设置accept为text/event-stream;
3.其他问题
服务端打算断开时,是否需要先得到客户端应答再断开?最近在浏览器控制台看了百度翻译的sse流式响应,感觉是每翻译完一个问题就结束了??
补充:sse是单项通道,只能服务器向浏览器推送
4.java代码参考
4.1 controller层
@RestController
public class ChatController {
@Autowired
private ChatService chatService;
// TODO: 2023/10/16 执行顺序
@CrossOrigin
@PostMapping(value = "/ask")
@SneakyThrows
public void chatGPT(@RequestBody ChatRequest request) {
chatService.chat(request);// TODO: 2023/10/16 执行顺序 2
}
@CrossOrigin
@GetMapping(value = "/link", produces = "text/event-stream;charset=utf-8")
@SneakyThrows
public SseEmitter link() {
return chatService.link();// TODO: 2023/10/16 执行顺序 1
}
@CrossOrigin
@PostMapping(value = "/stop")
@SneakyThrows
public void chatGPT() {
chatService.stop();// TODO: 2023/10/16 执行顺序 3
}
}
4.2 请求体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatRequest {
private String question;
}
4.3 接口
public interface ChatService {
void chat(ChatRequest request);
SseEmitter link();
void stop();
}
4.4 实现类
@Slf4j
@Service
public class ChatServiceImpl implements ChatService {
static HashMap<String, SseEmitter> map = new HashMap<>();
@SneakyThrows
@Override
public void chat(ChatRequest request) {
SseEmitter sseEmitter = map.get("222");
String question = request.getQuestion();
char[] chars = question.toCharArray();
for (int i = 0; i < chars.length; i++) {
sseEmitter.send(SseEmitter.event().id("111").data(chars[i]));
}
}
@SneakyThrows
@Override
public SseEmitter link() {
SseEmitter sseEmitter = new SseEmitter(0L);//设置超时时间,单位为毫秒
map.put("222", sseEmitter);
// >> 回调1:长链接完成后回调接口(即关闭连接时调用)
sseEmitter.onCompletion(() -> {
map.remove("222");
log.info("连接关闭, userId = {}, sessionId = {}, 时间戳 = {}", null, null, System.currentTimeMillis());// TODO: 2023/10/16 执行顺序 4
});
// >> 回调2:出现异常会调用此方法
sseEmitter.onError(new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
log.info("连接出错, userId = {}, sessionId = {}, 时间戳 = {}", null, null, System.currentTimeMillis());
sseEmitter.completeWithError(new RuntimeException("SSE 超时了"));
}
});
// >> 回调3:出现连接超时,会调用此方法
sseEmitter.onTimeout(() -> {
log.info("连接超时, userId = {}, sessionId = {}, 时间戳 = {}", null, null , System.currentTimeMillis());
sseEmitter.completeWithError(new RuntimeException("SSE 超时了"));
});
sseEmitter.send(SseEmitter.event().data("操作成功"));
return sseEmitter;
}
@SneakyThrows
@Override
public void stop() {
SseEmitter sseEmitter = map.get("222");
sseEmitter.send(SseEmitter.event().id("111").data("中断"));
sseEmitter.complete();
}
}
二、在终端通过CURL测试
1. 在idea打开终端Terminal
使用idea的终端窗口:
2. 示例接口的curl报文
2.1 请求连接的curl
curl -H "Accept: text/event-stream" http://localhost:9033/link
得到应答:
2.2 提问接口的curl(这个演示的是将输入的文字推送出来):
curl -X POST -H "Content-Type: application/json" -d "{\"question\": \"hhhhh\"}" http://localhost:9033/ask
提问后得到的响应:
2.3 mock服务主动断开的curl:
curl -X POST http://localhost:9033/stop
客户端收到的:
三、通过Postman测试
两个注意事项:
1.笔者一开始以为postman不支持测试SSE,后来发现是自己发送SSE请求时没有设置Accept: text/event-stream的请求头,导致发送不成功。
2.SSE的流式响应只会在link接口的postman窗口出现。用本文示例接口举例(link/ask/stop接口),postman先调link接口,再调ask接口,调完ask接口后,需要回到link接口的窗口下才能看到流式响应。因为端点在link接口那,在ask接口的窗口下是看不到的。
Postman 11+ 版本支持 SSE:
在 Postman 11 及以上版本中,可以直接测试 SSE 连接
使用方法:
创建新请求
选择请求方法为 GET
在地址栏输入 SSE 端点 URL
在 Headers 中添加 Accept: text/event-stream
发送请求后会保持连接并实时显示接收到的消息
更多推荐


所有评论(0)