SSE服务搭建

首先了解什么SSE服务?

SSE(Server-Sent Events,服务器发送事件)是一种基于 HTTP 的服务器向客户端单向推送实时数据的技术,它允许服务器主动向客户端发送事件流,适用于实时通知、数据更新等场景

特点:

  1. 单向通信:仅服务器向客户端推送数据(客户端不能通过 SSE 向服务器发送数据,需用 HTTP 或 WebSocket 补充)。
  2. 基于 HTTP:复用 HTTP 连接,无需额外协议(WebSocket 是独立协议),兼容性更好。
  3. 自动重连:客户端断开连接后会自动重试(可配置重连时间)。
  4. 文本数据:传输的数据是 UTF-8 编码的文本(通常用 JSON 格式)。
  5. 轻量级:协议简单,实现成本低,适合简单的实时场景。
java 复制代码
@Slf4j
public class SSEServer {

    //存放所有用户的SseEmitter
    private static final Map<String, SseEmitter> SSE_EMITTER_MAP=new ConcurrentHashMap<>();
    /**
     * 连接SSE
     * @return
     */
      public static SseEmitter connect(String userId){
         //设置超时时间,0表示不超时;默认是30秒,超时会抛出异常
          SseEmitter sseEmitter=new SseEmitter(0L);
          //注册回调方法
          //超时回调
          sseEmitter.onTimeout(timeOutCallBack(userId));
          //SSE完成后回调,完成后会调用的方法
          sseEmitter.onCompletion(completionCallBack(userId));
          //异常回调
          sseEmitter.onError(errorCallBack(userId));
          SSE_EMITTER_MAP.put(userId,sseEmitter);
          log.info("用户{}连接SSE成功",userId);
          return sseEmitter;
      }
      /**
       * 发送SSE消息
       * @param userId
       * @param message
       * @param msgType
       */
      public static void senMessage(String userId,String message,SSEMsgType msgType){
            if (CollectionUtil.isEmpty(SSE_EMITTER_MAP)){
                return;
            }
            if (SSE_EMITTER_MAP.containsKey(userId)) {
                SseEmitter sseEmitter = SSE_EMITTER_MAP.get(userId);
                //发送事件
                 sendEvent(sseEmitter,userId,message,msgType);
            }

      }
      /**
       * 发送SSE事件
       * @param sseEmitter
       * @param userId
       * @param message
       * @param msgType
       */
      private static void sendEvent(SseEmitter sseEmitter,
                                   String userId,
                                   String message,
                                   SSEMsgType msgType){

          try{
              SseEmitter.SseEventBuilder eventBuilder = SseEmitter.event()
                      .id(userId)
                      .name(msgType.type)
                      .data(message);
              sseEmitter.send(eventBuilder);
          }catch (Exception e){
              log.error("用户{}发送SSE消息异常",userId,e);
              remove(userId);
          }



      }
      /**
       * 异常回调
       * @param userId
       * @return
       */
      public static Consumer<Throwable> errorCallBack(String userId){
          return throwable -> {
              log.error("用户{}SSE连接异常",userId,throwable);
              //异常处理逻辑
             remove(userId);
          };
      }
      /**
       * 超时回调
       * @param userId
       * @return
       */
      public static Runnable timeOutCallBack(String userId){
          return () -> {
              log.info("用户{}超时",userId);
              //超时处理逻辑
             remove(userId);
          };
      }
      /**
       * 完成回调
       * @param userId
       * @return
       */
      public static Runnable completionCallBack(String userId){
          return () -> {
              log.info("用户SSE{}完成",userId);
              //完成处理逻辑
             remove(userId);
          };
      }
      /**
       * 移除用户的SseEmitter
       * @param userId
       */
      public static void remove(String userId){
          SSE_EMITTER_MAP.remove(userId);
          log.info("移除用户{}的SseEmitter",userId);
      }
}

定义枚举类型,代表SSE返回的消息类型

java 复制代码
/**
 * SSE消息类型
 */
public enum SSEMsgType {
   MESSAGE("message","单词发送的普通类型消息"),
   ADD("add","消息追加,适用于流式消息"),
   FINISH("finish","消息完成"),
   CUSTOM_EVENT("custom_event","自定义事件"),
   DONE("done","消息完成,适用于流式消息");



   public final String type;
   public final String value;

   SSEMsgType(String type,String value){
      this.type=type;
      this.value=value;
   }

}
相关推荐
一直都在5727 分钟前
SpringBoot3 框架快速搭建与项目工程详解
java·开发语言
子云之风7 分钟前
LSPosed 项目编译问题解决方案
java·开发语言·python·学习·android studio
小北方城市网8 分钟前
SpringBoot 全局异常处理与接口规范实战:打造健壮可维护接口
java·spring boot·redis·后端·python·spring·缓存
独自破碎E10 分钟前
什么是Spring IOC
java·spring·rpc
lendsomething14 分钟前
graalvm使用实战:在java中执行js脚本
java·开发语言·javascript·graalvm
烤麻辣烫15 分钟前
java进阶--刷题与详解-2
java·开发语言·学习·intellij-idea
期待のcode15 分钟前
性能监控工具
java·开发语言·jvm
Chan1623 分钟前
【 微服务SpringCloud | 方案设计 】
java·spring boot·微服务·云原生·架构·intellij-idea
浪扼飞舟33 分钟前
C#(多线程和同步异步)
java·开发语言
hanqunfeng39 分钟前
(三十三)Redisson 实战
java·spring boot·后端