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;
   }

}
相关推荐
一定要AK4 小时前
Spring 入门核心笔记
java·笔记·spring
A__tao4 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
KevinCyao4 小时前
java视频短信接口怎么调用?SpringBoot集成视频短信及回调处理Demo
java·spring boot·音视频
迷藏4944 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
總鑽風5 小时前
搭建Spring Boot + ELK日志平台,实现可视化日志监控
spring boot·elk·macos
不吃香菜学java5 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
wuxinyan1235 小时前
Java面试题47:一文深入了解Nginx
java·nginx·面试题
新知图书5 小时前
搭建Spring Boot开发环境
java·spring boot·后端
皮皮林5515 小时前
SpringBoot 4 最被低估的新特性:Spring Data AOT
spring boot
冰河团队5 小时前
一个拉胯的分库分表方案有多绝望?整个部门都在救火!
java·高并发·分布式数据库·分库分表·高性能