在客户端使用 OkHttp 框架 的 EventSource
时,如果客户端调用 eventSource.cancel()
,会触发 EventSourceListener
的 onClosed()
方法。同时,服务端会检测到客户端断开连接,并触发 SseEmitter
的 onCompletion()
事件。
1. 客户端调用 eventSource.cancel()
的行为
客户端代码示例
import okhttp3.*;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;
public class SseClient {
public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://localhost:8080/sse-stream")
.build();
EventSource.Factory factory = EventSources.createFactory(client);
EventSource eventSource = factory.newEventSource(request, new EventSourceListener() {
@Override
public void onOpen(EventSource eventSource, Response response) {
System.out.println("SSE connected!");
}
@Override
public void onEvent(EventSource eventSource, String id, String type, String data) {
System.out.println("Received event: " + data);
}
@Override
public void onClosed(EventSource eventSource) {
System.out.println("SSE closed by client.");
}
@Override
public void onFailure(EventSource eventSource, Throwable t, Response response) {
System.err.println("SSE error: " + t.getMessage());
}
});
// 模拟客户端主动取消连接
try {
Thread.sleep(5000); // 等待 5 秒
eventSource.cancel(); // 客户端主动取消连接
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
客户端行为
- 当调用
eventSource.cancel()
时:- 客户端会主动关闭连接。
- 触发
EventSourceListener
的onClosed()
方法。 - 不会触发
onFailure()
,因为这是客户端主动取消的行为,而不是错误。
2. 服务端的响应
服务端代码示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@RestController
public class SseController {
@GetMapping("/sse-stream")
public SseEmitter streamEvents() {
SseEmitter emitter = new SseEmitter();
// 监听客户端断开连接
emitter.onCompletion(() -> {
System.out.println("Client disconnected: onCompletion");
});
// 监听连接超时
emitter.onTimeout(() -> {
System.out.println("Connection timeout: onTimeout");
});
// 模拟发送事件
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
emitter.send(SseEmitter.event().data("Event " + i));
Thread.sleep(1000);
}
} catch (Exception e) {
emitter.completeWithError(e);
}
}).start();
return emitter;
}
}
服务端行为
- 当客户端调用
eventSource.cancel()
时:- 服务端会检测到客户端断开连接。
- 触发
SseEmitter
的onCompletion()
事件。 - 如果设置了
onTimeout()
,但客户端是主动断开连接,不会触发onTimeout()
。
3. 执行流程
- 客户端:
- 连接成功后,接收事件。
- 调用
eventSource.cancel()
,触发onClosed()
。
- 服务端:
- 检测到客户端断开连接,触发
onCompletion()
。
- 检测到客户端断开连接,触发
4. 总结
客户端行为 | 客户端回调方法 | 服务端回调方法 |
---|---|---|
调用 eventSource.cancel() |
onClosed() |
onCompletion() |
网络断开/超时 | onFailure() |
onCompletion() 或 onTimeout() |
eventSource.cancel()
是客户端主动断开连接的行为,会触发onClosed()
。- 服务端通过
onCompletion()
检测到客户端断开连接,并执行相应的清理逻辑。