🐶 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 上下文中的其他对象和资源