单向通信 SSE 接口示例
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
@RestController
public class SseController {
// 创建一个线程池用于异步发送消息
private final ExecutorService executor = Executors.newFixedThreadPool(10);
/*
* SSE 接口示例
* */
@GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter sse() {
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE); // 默认超时时间为30秒,这里设定为永不超时
// 用于标记任务是否已完成
AtomicBoolean isCompleted = new AtomicBoolean(false);
// 添加完成回调,确保任务在连接断开时能正确终止
emitter.onCompletion(() -> {
System.out.println("SSE连接已完成");
if (isCompleted.compareAndSet(false, true)) {
System.out.println("SSE消息发送任务已完全结束");
// 可以在这里添加其他结束后的处理逻辑
// 例如:记录日志、清理资源、通知其他服务等
}
});
emitter.onTimeout(() -> {
System.out.println("SSE连接超时");
if (isCompleted.compareAndSet(false, true)) {
System.out.println("SSE消息发送任务因超时而结束");
}
// 不主动调用complete(),保持连接
});
emitter.onError((error) -> {
System.out.println("SSE连接发生错误: " + error.getMessage());
if (isCompleted.compareAndSet(false, true)) {
System.out.println("SSE消息发送任务因错误而结束");
}
// 不主动调用completeWithError(),保持连接
});
executor.execute(() -> {
try {
String planSendMessage = "欢迎访问xxx系统,X一对一助手已上线!";
for (int i = 0; i < planSendMessage.length(); i++) {
// 检查连接是否仍然有效后再发送
if (!isCompleted.get()) {
emitter.send(SseEmitter.event().name("message").data(planSendMessage.charAt(i)));
Thread.sleep(100); // 每100毫秒发送一次
} else {
break;
}
}
// 发送完成后发送结束标识,但不关闭连接
if (!isCompleted.get()) {
emitter.send(SseEmitter.event().name("end").data("END"));
System.out.println("消息发送完成,但连接保持开启");
}
} catch (IOException | InterruptedException e) {
System.err.println("发送过程中发生异常: " + e.getMessage());
// 即使发生异常也不关闭连接
}
});
return emitter;
}
}
<!DOCTYPE html>
<html>
<head>
<title>SSE 示例</title>
</head>
<body>
<h1>Server-Sent Events 测试</h1>
<div id="output"></div>
<script>
const eventSource = new EventSource('http://10.5.44.70:10005/sse');
eventSource.onmessage = function (event) {
// 在同一行追加显示,使用span元素分隔
let message = event.data;
if (message.startsWith('"') && message.endsWith('"')) {
message = message.substring(1, message.length - 1);
}
// 在同一行追加显示
if (output.innerHTML.length > 0) {
output.innerHTML += ' ' + message;
} else {
output.innerHTML = message;
}
// 如果内容过长,自动滚动到右侧
output.scrollLeft = output.scrollWidth;
};
eventSource.addEventListener('message', function (event) {
console.log('收到消息:', event.data);
});
eventSource.onerror = function (err) {
console.error("EventSource failed:", err);
};
</script>
</body>
</html>
作者:人间春风意
扫描左侧的二维码可以赞赏

本作品采用署名-非商业性使用-禁止演绎 4.0 国际 进行许可。

浙公网安备 33010602011771号