跳到主要内容

SSE 订阅推送

平台基于 Server-Sent Events(SSE)提供消息订阅与推送能力,支持服务端在数据变更后将事件实时下发到前端。订阅者可按业务主题精确订阅,也可以一次性订阅全部主题的全量消息。

适用场景

  • 前端实时刷新字典、页面配置、流程状态等数据缓存。
  • 聚合通知、监控大盘、调试页需要接收平台所有主题的事件流。

订阅端点

订阅端点统一挂在 /subscribe 下,返回 text/event-stream 长连接流:

端点说明
GET /subscribe/{topic}订阅指定主题。topic 为非空字符串,否则返回 400 Bad Request
GET /subscribe/topic/all订阅全部主题。平台向任意主题推送的消息都会复制一份到该流。

认证

订阅端点受 DefaultSecurityInterceptor 保护,请求头需携带有效的 Authorization,支持的凭证形式包括 JWTBearerBearer(OAuth2)、Anonymous 等。订阅本身不区分主题权限——任意已认证用户均可订阅任意主题或全量主题流。

连接生命周期

每个连接的超时时间为 30 分钟。连接完成(completion)、超时(timeout)或异常(error)后,订阅关系会被自动清理;推送过程中识别到失效连接时也会即时移除,避免内存泄漏。客户端断线后,浏览器 EventSource 会按服务端下发的 retry: 3000(毫秒)自动重连。

客户端订阅

服务端未在事件流中设置自定义 event: 名称,因此消息统一以默认 message 事件下发,客户端通过 onmessage 接收。消息体为 JSON 字符串,其结构由推送方决定。

订阅单个主题

const source = new EventSource('/subscribe/upgrade_page_topic');

source.onmessage = (event) => {
const payload = JSON.parse(event.data);
console.log(payload);
// 示例:{ "DATA": "UpgradePageEvent", "PAGE_ID": 12, "EXTEND_ID": 3 }
};

订阅全部主题

const source = new EventSource('/subscribe/topic/all');

source.onmessage = (event) => {
const payload = JSON.parse(event.data);
console.log(payload);
};

服务端推送

推送通过服务端代码触发,不提供 HTTP 推送端点。调用 SseHelper.push(...) 即可将消息广播到对应主题的全部订阅者,同时同步复制到 /subscribe/topic/all 的全量订阅者。

推送 API

// 构造消息:topic 为主题名称,data 为任意可序列化为 JSON 的对象
SseMessage message = new SseMessage("upgrade_page_topic", payload);
SseHelper.push(message);

SseHelper 主要方法:

方法说明
SseHelper.push(SseMessage message)向指定主题推送消息。message.topic 不能为空,否则抛出 IllegalArgumentException
SseHelper.subscribe(String topic)创建指定主题的 SseEmitter(供控制器返回)。
SseHelper.subscribeAll()创建全量主题的 SseEmitter
SseHelper.getActiveTopics()返回当前有活跃订阅者的主题集合。

SseMessage 仅包含两个字段:

public class SseMessage {
private String topic; // 主题名称
private Object data; // 负载,序列化为 JSON 下发
}

示例:在事件处理中推送

平台内置多处推送调用,通常由领域事件触发。以页面配置升级为例:

@Override
public void handle() {
Map<String, Object> data = new HashMap<>();
data.put("DATA", getEventCode()); // "UpgradePageEvent"
data.put("PAGE_ID", pageId);
data.put("EXTEND_ID", extendId);
SseHelper.push(new SseMessage("upgrade_page_topic", data));
}

业务侧推送消息时,建议在负载中约定一个标识字段(如示例中的 DATA),便于客户端区分事件类型。

平台内置主题

平台已通过领域事件接入以下主题,业务可直接订阅:

主题触发时机负载字段
upgrade_dictionary_topic数据字典项变更DATADICT_ID
upgrade_page_topic页面配置变更DATAPAGE_IDEXTEND_ID
upgrade_state_workflow_topic状态机流程定义变更DATAPROC_DEF_ID

兼容性

订阅能力向后兼容:新增的全量主题订阅与既有按主题订阅相互独立,不影响现有调用方;推送时按主题订阅者与全量订阅者各收到一份副本,互不干扰。