🐶 SSE 控制器
# SSE 控制器
SSE 控制器,即ForestSSE
对象实例,是用于发起请求、建立连接、进行事件监听,以及维持整个 SSE 事件流生命周期的对象。可以把一个 SSE 控制器对象理解为一个 SSE 事件流的会话。
一个 SSE 事件流就有一个对应的 SSE 控制器,多个不同 SSE 请求就有多个对应的 SSE 控制器,它们之间相互独立,互不影响。
获取 SSE 控制器的方式也很简单,可以通过声名式接口返回ForestSSE
对象,也可以通过编程式接口中ForestRequest
请求对象的sse()
方法返回得到ForestSSE
对象。
关于如何具体获得 SSE 控制器、以及件监听和关闭,请参见《声明式 SSE 接口》或 《编程式 SSE 接口》
# 自定义 SSE 控制器
自定义一个 SSE 控制器需要继承com.dtflys.forest.http.ForestSSE
类,并且可以重写其中的onOpen
方法和onClose
方法,用于实现 SSE 开始监听和结束监听时的处理代码
而通过重写onMessage
方法,可以处理 SSE 消息
// 自定义 SSE 控制器类,需要继承 ForestSSE
public class MySSEHandler extends ForestSSE {
// opOpen 方法可重写,可不重写
@Override
protected void onOpen(EventSource eventSource) {
// SSE 开始监听时调用
// eventSource 为 EventSource 事件源对象
eventSource.getRequest(); // 获取 Forest 请求对象
eventSource.getResponse(); // 获取 Forest 响应对象
}
// onClose 方法可重写,可不重写
@Override
protected void onClose(EventSource eventSource) {
// SSE 结束监听时调用
}
// 1.6.4+ 版本可以重写 onMessage 方法来接收 SSE 消息
@Override
public void onMessage(EventSource event) {
event.id(); // 获取消息名称为 id 的消息值
event.event(); // 获取消息名称为 event 的消息值
event.data(); // 获取消息名称为 data 的消息值
event.retry(); // 获取消息名称为 retry 的消息值
event.value("text"); // 获取非标准消息名称为 text 的消息值
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# SSE 事件处理方法
然后就可以在自定义的 SSE 控制器类中声明和定义 SSE 事件处理方法了
// 自定义 SSE 控制器类,需要继承 ForestSSE
public class MySSEHandler extends ForestSSE {
// opOpen 方法可重写,可不重写
@Override
protected void onOpen(EventSource eventSource) {
// SSE 开始监听时调用
// eventSource 为 EventSource 事件源对象
eventSource.getRequest(); // 获取 Forest 请求对象
eventSource.getResponse(); // 获取 Forest 响应对象
}
// onClose 方法可重写,可不重写
@Override
protected void onClose(EventSource eventSource) {
// SSE 结束监听时调用
}
// 1.6.4+ 版本可以重写 onMessage 方法来接收 SSE 消息
@Override
public void onMessage(EventSource event) {
event.id(); // 获取消息名称为 id 的消息值
event.event(); // 获取消息名称为 event 的消息值
event.data(); // 获取消息名称为 data 的消息值
event.retry(); // 获取消息名称为 retry 的消息值
event.value("text"); // 获取非标准消息名称为 text 的消息值
}
// 只处理消息名为 data 的事件
@SSEDataMessage
public void onSSEData(EventSource eventSource, @SSEName String name, @SSEValue String value) {
// 处理事件消息名称为 data 的事件
// 声明的方法名和处理的事件消息名称没有关系,方法名可以是 onData、onSseData、onMessage、xxx、以及任何名称都可以
// @SSEName 注解修饰的参数 name 为事件消息名称 (同 eventSource.name())
// @SSEValue 注解修饰的参数 value 为事件消息的值
eventSource.sse(); // 获取 SSE 控制器
eventSource.request(); // 获取 Forest 请求对象
eventSource.response(); // 获取 Forest 响应对象
eventSource.rawData(); // 获取事件消息的原始数据
eventSource.name(); // 获取事件消息的名称,如 data、event、id 等
eventSource.value(); // 获取事件消息的值,返回字符串类型数据
// 获取事件消息的值,并将消息转换为指定的自定义类型
eventSource.value(MyUser.class);
// 获取事件消息的值,并将消息转换为指定的自定义泛型类型
eventSource.value(new TypeReference<List<MyUser>>() {});
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
关于具体如何声明和定义 SSE 事件消息的处理方法,请参见《SSE事件处理方法》
# 共享变量
因为每个 SSE 控制器 (包括自定义 SSE 控制器) 的对象对于 SSE 请求来说都是一对一独立的,所以在 SSE 控制器中定义的变量属性也是对外部独立的
那么基于这一点就可以用于在同一个 SSE 事件流中通过共享变量实现跨事件、跨生命周期的数据传递,而不用担心不同 SSE 请求之间的数据污染
// 自定义 SSE 控制器类,需要继承 ForestSSE
public class MySSEHandler extends ForestSSE {
// 共享变量
private final StringBuffer buffer = new StringBuffer();
@Override
protected void onOpen(EventSource eventSource) {
// SSE 开始监听时调用
buffer.append("SSE Open").append("\n");
}
@Override
protected void onClose(EventSource eventSource) {
// SSE 结束监听时调用
buffer.append("SSE Close");
}
@SSEMessage("data")
public void onData(@SSEName String name, @SSEValue String value) {
// 处理事件消息名称为 data 的事件
buffer.append("Receive ").append(name).append(": ").append(value).append("\n");
}
// 获取共享变量中的值
public StringBuffer getStringBuffer() {
return buffer;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
注意
不能注入 Spring 上下文
但也由于一对一独立的特性,SSE 控制器不能注入到 Spring 上下文中
同时也不能在自定义 SSE 控制器中注入 Spring 上下文中的其他对象和资源