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

}
相关推荐
wuminyu32 分钟前
Kafka中sendfile与mmap实现机制解析
java·linux·c语言·jvm·c++
考虑考虑2 小时前
Java实现hmacsha256加密算法
java·后端·java ee
captain3762 小时前
▲网络原理(2)-TCP
java·服务器·网络·tcp/ip·java-ee
MetaLite2 小时前
SpringBoot接口分层规范-外网网关内部服务与参数边界
java·数据库·spring boot
Co_Hui2 小时前
Java 线程状态
java
凤山老林3 小时前
聊聊企业级 API 安全:Spring Boot 落地 OAuth 2.1、mTLS 与接口签名防篡改
spring boot·后端·安全·oauth
土司大王3 小时前
LeetCode hot100——35.搜索插入位置:Java 二分模板、左闭右开区间与插入点分析
java·算法·leetcode
土司大王3 小时前
LeetCode hot100——34.在排序数组中查找元素的第一个和最后一个位置:Java 二分模板、边界分析
java·算法·leetcode
金金计较.3 小时前
Go语言-3
java·开发语言·golang
Wang's Blog4 小时前
Java框架快速入门: Spring Security+OAuth2之元注解简化权限表达式
java·数据库·spring