springboot使用SSE

springboot使用SSE

起男 64 2025-01-22

springboot使用SSE

SSE(server send event)服务端主动推送技术。html5新标准,用来从服务端实时推送数据到浏览器

直接建立在当前http连接上,本质上是保持一个http长连接,轻量简单的服务器数据推送场景,可以使用SSE,SSE技术是基于单工通信模式

服务端

@RequestMapping("sse")
@RestController
@Slf4j
public class SseController {

    //缓存连接
    private static final Map<String, SseEmitter> MAP = new ConcurrentHashMap<>();

    /**
     * 建立连接
     * @param id
     * @return
     */
    @SneakyThrows
    @GetMapping("subscribe/{id}")
    public SseEmitter subscribe(@PathVariable String id){
        log.info("subscribe {}",id);
        SseEmitter sseEmitter = new SseEmitter(30000L);
        MAP.put(id,sseEmitter);
        sseEmitter.onCompletion(()->{
            log.info("{}完成",id);
            MAP.remove(id);
        });
        sseEmitter.onTimeout(()->{
            log.info("{}超时",id);
            MAP.remove(id);
        });
        //响应前端,并设置重试时间为1秒
        sseEmitter.send(SseEmitter.event().reconnectTime(1000).data("连接成功"));
        return sseEmitter;
    }

    /**
     * 发送消息
     * @param id
     * @param msg
     * @return
     */
    @SneakyThrows
    @GetMapping("push/{id}/{msg}")
    public String push(@PathVariable String id,@PathVariable String msg){
        log.info("push {} {}",id,msg);
        SseEmitter sseEmitter = MAP.get(id);
        if (sseEmitter!=null){
            sseEmitter.send(SseEmitter.event().name("msg").data(msg));
        }
        return "ok";
    }

    /**
     * 断开连接
     * @param id
     * @return
     */
    @GetMapping("over/{id}")
    public String over(@PathVariable String id){
        SseEmitter sseEmitter = MAP.get(id);
        if (sseEmitter!=null){
            sseEmitter.complete();
            MAP.remove(id);
        }
        return "ok";
    }
}

浏览器

  • 访问sse/subscribe/{id}建立连接,并监听
  • 访问sse/push/{id}/{msg}发送消息
  • 访问sse/over/{id}断开连接