用于与前端链接消息触发


 @Resource
    private SseMessageService sseMessageService;
    @Resource
    private ConfigPrinterConfig configPrinter;

    @CrossOrigin(origins = "*", allowedHeaders = "GET")
    @GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamSseMvc(String userId, String uniqueKey, HttpServletResponse response) {
        response.setContentType("text/event-stream;charset=UTF-8");

        SseEmitter emitter = new SseEmitter(Long.valueOf(configPrinter.getSseRequestTimeOut()));
        sseMessageService.setUniqueKey(uniqueKey);
        sseMessageService.addEmitter(userId, emitter);
        sseMessageService.sendMessage(userId, "初始连接", "init");
        return emitter;
    }

private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

@Setter
private String uniqueKey = "";

public void addEmitter(String userId, SseEmitter emitter) {
    emitters.put(userId, emitter);
    log.info(DateUtils.getTime() + " 连接用户 userId:{}", userId);
    emitter.onTimeout(() -> {
        emitters.remove(userId);
        emitter.complete();
    });

    emitter.onCompletion(() -> {
        emitters.remove(userId);
        emitter.complete();
    });

    emitter.onError((e) -> {
        emitters.remove(userId);
        emitter.completeWithError(e);
    });

}

@Async()
public void removeEmitter(String userId, SseEmitter emitter) {
    emitters.remove(userId);
    emitter.complete();
}

@Async()
public void sendMessage(String userId, String message, String label) {
    SseEmitter emitter = emitters.get(userId);
    if (emitter != null) {
        try {
            // 创建一个 JSON 对象
            Map<String, String> map = new HashMap<>();
            map.put("label", label);
            map.put("userId", userId);
            map.put("message", message);
            map.put("uniqueKey", uniqueKey);
            map.put("id", String.valueOf(UUID.randomUUID()));
            map.put("dateTimeNow", DateUtils.dateTimeNow());
            emitter.send(new JSONObject(map).toString());
        } catch (Exception e) {
            emitter.completeWithError(e);
            removeEmitter(userId, emitter);
        }
    }
}

解释


在使用 Server-Sent Events (SSE) 的场景中,消息的接收方通常是前端的 JavaScript 客户端。以下是消息接收的基本流程:

1. 前端设置 SSE 连接

在前端,你需要使用 JavaScript 创建一个 EventSource 对象来连接后端的 SSE 端点。例如:

const eventSource = new EventSource('http://你的服务器地址/sse?userId=用户ID&uniqueKey=唯一键');

eventSource.onmessage = function(event) {

    const data = JSON.parse(event.data);

    console.log('Received message:', data);

    // 处理接收到的消息

};

// 处理连接关闭

eventSource.onclose = function() {

    console.log('Connection closed');

};

// 处理错误

eventSource.onerror = function(error) {

    console.error('Error occurred:', error);

};

2. 后端发送消息

在你的 SseMessageService 中,通过 emitter.send(...) 发送的消息会通过 SSE 通道推送到连接的客户端。客户端会通过 onmessage 事件接收到这些消息。

3. 消息的结构

你在后端构造的消息(例如包含 label、`userId`、`message` 等字段)会在前端解析,前端可以根据消息内容进行相应的处理,例如更新 UI 或执行其他逻辑。

总结

- 接收方: 前端 JavaScript 客户端通过 EventSource 接收后端推送的消息。

- 发送方: 后端通过 SseEmitter 实现消息的推送。

如果有更具体的问题或者需要深入探讨,请告诉我!

刚学java菜鸡,永劫无间蚀月,王者荣耀王者,金铲铲小铂金,第五人格菜鸡,原神开服玩家,星穹铁道菜鸡,崩坏的菜鸡,闪耀暖暖,和平精英,LOL,CSGO,以及三A大作收集者等等。。。