springboot整合SSE(Server Send Event)推送流信息

Spring boot整合SSE实现服务器实时推送流信息代码实现

本文只描述了sse的代码使用

服务端

1、控制层的链接接口必须返回SseEmitter,前端才能获取到该链接
在这里插入图片描述
2、业务层写业务逻辑即可,sse相关逻辑可以放在通用类中
在这里插入图片描述

工具类

1、sse发送消息是通过阻塞队列进行触发的

package com.zbnsec.simulator.framework.sse;

import com.zbnsec.simulator.project.topology.controller.dto.TopologyChangeDTO;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * sse工具类
 *
 * @author user
 */
@Slf4j
@Component
public class SSEServer {

    /**
     * 当前连接数
     */
    private static AtomicInteger count = new AtomicInteger(0);

    private static Map<String, SseEmitter> cache = new ConcurrentHashMap<>();

    private static final BlockingQueue<TopologyChangeDTO> QUEUE = new LinkedBlockingQueue<>();

    /**
     * 创建sse链接
     *
     * @param clientId 客户端id
     * @return
     */
    public static SseEmitter connect(String clientId, TopologyChangeDTO topologyChangeDTO) {
        //设置超时时间,0表示不过期,默认是30秒,超过时间未完成会抛出异常
        SseEmitter sseEmitter = new SseEmitter(0L);
        pushMessage(sseEmitter, topologyChangeDTO);
        // 注册回调
        // 通信完成
        sseEmitter.onCompletion(() -> cache.remove(clientId));
        sseEmitter.onError(e -> log.error("SSEServer.connect error:", e));
        /*sseEmitter.onTimeout(timeOutCallBack(userId));*/
        cache.put(clientId, sseEmitter);
        //数量+1
        count.getAndIncrement();
        log.info("SSEServer create new sse connect ,current clientId:{}, 连接数={}", clientId, count);
        return sseEmitter;
    }

    /**
     * 关闭sse链接
     *
     * @param clientId 客户端id
     */
    public static void close(String clientId) {
        SseEmitter sseEmitter = cache.get(clientId);
        if (sseEmitter != null) {
            sseEmitter.complete();
            cache.remove(clientId);
        }
    }

    private static Thread SEND_THREAD;

    @PostConstruct
    public void pushMessage() {
        log.info("SSEServer start simulator SSE push thread.");
        SEND_THREAD = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    TopologyChangeDTO message = pull();
                    if (message != null && !message.getChange().equals(message.getLastChange())) {
                        for (Map.Entry<String, SseEmitter> entry : cache.entrySet()) {
                            pushMessage(entry.getValue(), message);
                        }
                    }
                }
            }
        }, "Simulator-SSE-Push");
        SEND_THREAD.setDaemon(true);
        SEND_THREAD.start();
        log.info("SSEServer start simulator SSE push thread completed.");
    }

    private static void pushMessage(SseEmitter sseEmitter, TopologyChangeDTO message) {
        try {
            sseEmitter.send(
                    SseEmitter
                            .event()
                            .data(message)
                            .reconnectTime(3000)
            );
        } catch (Exception e) {
            log.error("SSEServer pushMessage error:", e);
        }
    }


    public static void pushQueue(TopologyChangeDTO message) {
        if (null == message) {
            return;
        }
        try {
            QUEUE.put(message);
        } catch (InterruptedException exception) {
            log.error("SSEServer pushQueue:", exception);
        }
    }

    public static TopologyChangeDTO pull() {
        try {
            return QUEUE.take();
        } catch (InterruptedException exception) {
            log.error("SSEServer io thread interrupted", exception);
            return null;
        }
    }
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot创建SSE客户端的步骤如下: 1. 导入相关依赖:在`pom.xml`文件中添加`spring-boot-starter-web`和`spring-boot-starter-websocket`的依赖。 2. 创建SSE客户端类:创建一个Java类,用于发送SSE请求和接收服务端推送消息。 3. 使用RestTemplate发送SSE请求:使用`RestTemplate`类发送GET请求,并设置`Accept`头为`text/event-stream`,以指定接收SSE响应。 4. 处理SSE响应:利用`RestTemplate`的`exchange`方法发送SSE请求,并使用`SseEmitter`类来处理SSE响应。可以使用`onCompletion`、`onTimeout`、`onError`等方法来处理SSE连接关闭或出错的情况。 5. 接收服务端推送消息:在SSE响应的回调方法中,可以通过`SseEmitter`的`send`方法发送消息给客户端,并使用`SseEmitter`的`complete`方法标识SSE连接结束。 下面是一个示例代码: ``` import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.net.URI; import java.time.Duration; @Component public class SseClient { public void createSseClient() { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setAccept(MediaType.TEXT_EVENT_STREAM); RequestEntity<?> requestEntity = RequestEntity.get(URI.create("http://localhost:8080/sse/CreateSseConnect")) .headers(headers) .build(); ResponseEntity<Void> responseEntity = restTemplate.exchange(requestEntity, Void.class); SseEmitter sseEmitter = SseEmitter.class.cast(responseEntity.getBody()); sseEmitter.onCompletion(() -> { // SSE连接关闭的处理逻辑 }); sseEmitter.onTimeout(() -> { // SSE连接超时的处理逻辑 }); sseEmitter.onError((e) -> { // SSE连接出错的处理逻辑 }); sseEmitter.onCompletion(() -> { // SSE连接结束的处理逻辑 }); sseEmitter.send("Hello, server!"); // 接收服务端推送消息 sseEmitter.onCompletion(() -> { // SSE连接结束的处理逻辑 }); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值