#### SSE 简介
Server-Sent Events(SSE)是一种允许服务器主动向客户端发送信息的技术。与 WebSocket 不同,SSE 是单向通信,仅服务器能向客户端发送数据。这使得 SSE 非常适合于需要服务器实时推送数据但客户端不需要发送信息的场景,例如实时通知和更新。
#### tio-boot 中整合 SSE 的步骤
整合 SSE 到 tio-boot 框架中可以让你的应用具备实时数据推送的能力。以下是在 tio-boot 框架中创建一个简单的 SSE 应用的步骤和代码示例:
##### 步骤 1: 创建 SSE Controller
首先,创建一个名为 `SseController` 的类,并用 `@RequestPath` 注解标记该类和方法。该方法将处理来自 `/sse` 路径的 SSE 请求。
```java
package com.litongjava.ai.chat.controller;
import com.litongjava.tio.core.Tio;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.http.server.sse.SsePacket;
import com.litongjava.tio.server.ServerChannelContext;
import lombok.extern.slf4j.Slf4j;
@RequestPath("/sse")
@Slf4j
public class SseController {
@RequestPath
public HttpResponse conversation(HttpRequest request, ServerChannelContext channelContext) {
// ... (代码继续)
}
}```
##### 步骤 2: 设置 SSE 请求头并发送响应
在 `conversation` 方法中,首先设置 SSE 请求头,并发送一个空的响应来初始化 SSE 连接。
```java
// 设置 SSE 请求头
HttpResponse httpResponse = new HttpResponse(request).setServerSentEventsHeader();
Tio.send(channelContext, httpResponse);
log.info("已经响应请求头");
```
##### 步骤 3: 发送 SSE 消息
使用 `SsePacket` 来构造并发送 SSE 消息。在这个例子中,我们通过一个循环发送了 10 条消息。
```java
new Thread(() -> {
for (int i = 0; i < 10; i++) {
// ... (循环内容)
}
// 手动移除连接
Tio.remove(channelContext, "remove sse");
}).start();```
##### 步骤 4: 测试 SSE 功能
要测试你的 SSE 服务,你可以使用 curl 命令访问 SSE 路径:
```
curl http://localhost/sse
```
测试结果应该显示一系列格式化的 SSE 消息:
```
id:1 event:message data:This is message 0 id:2 event:message data:This is message 1 ...
```
每条消息都包含一个唯一的 `id`,事件类型 `event`,以及实际的消息内容 `data`。
#### 完整的Cotnroller
```
package com.litongjava.ai.chat.controller;
import com.litongjava.tio.core.Tio;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.http.server.sse.SsePacket;
import com.litongjava.tio.server.ServerChannelContext;
import lombok.extern.slf4j.Slf4j;
@RequestPath("/sse")
@Slf4j
public class SseController {
@RequestPath
public HttpResponse conversation(HttpRequest request, ServerChannelContext channelContext) {
// 设置sse请求头
HttpResponse httpResponse = new HttpResponse(request).setServerSentEventsHeader();
// 手动发送消息到客户端,因为已经设置了sse的请求头,所以客户端的连接不会关闭
Tio.send(channelContext, httpResponse);
log.info("已经相应请求头");
new Thread(() -> {
for (int i = 0; i < 10; i++) {
String id = i + "";
String eventName = "message";
String data = "This is message " + i;
SsePacket ssePacket = new SsePacket().eventId(id).name(eventName).data(data);
// 再次向客户端发送消息
Tio.send(channelContext, ssePacket);
log.info("发送数据:{}", i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//手动移除连接
Tio.remove(channelContext, "remove sse");
}).start();
// 告诉处理器不要将消息发送给客户端
return new HttpResponse().setSend(false);
}
}```
#### 总结
通过上述步骤,你可以在 tio-boot 框架中成功整合 SSE,从而使你的应用能够实时地向客户端推送数据。这种方法的优点在于其简单性和低延迟,非常适用于需要服务器实时更新的场景。