SseEmitter
SseEmitter是spring框架中用于处理服务器发送事件的一个工具类,,
sse : server sent event
服务器主动推送到客户端,,,
spring事件基于观察者模式,也可以看作一种发布订阅,,
有消息推送之后,会去遍历每个消费者,也就是监听器,去消费信息,,,,,
客户端首先将自己添加为消费者,,等到某个事件发布的时候,去触发对应的消费者,,执行
页面加载的时候,就去发送一个请求,将自己变成消费者,,在离开页面的时候,把自己从消费者中移除出去
遇到的问题,,google浏览器,不让直接播放mp3,,,
document点击之后,去设置这个audio的src,,然后就能播放
解决:https://blog.csdn.net/w1299395323/article/details/107332861/
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<button onclick="handleClick()">play</button>
<audio id="audio" src="tipsMp3.mp3">
<!-- <source src="tipsMp3.mp3" type="audio/mp3">-->
</audio><script>var audioDom = document.querySelector("#audio");// audioDom.src="./tipsMp3.mp3"document.addEventListener("click",function (event){console.log("hehe")audioDom.src="./tipsMp3.mp3"})const eventSource = new EventSource("http://localhost:8092/manager/sse/connection/123")eventSource.onmessage = function (event){if (event.data ==="Heartbeat"){return}console.log(event,"event")console.log("收到消息",event.data)audioDom.play()}eventSource.onerror = function (event){console.log(event,"event","err")if (eventSource.readyState === EventSource.CLOSED){console.log("连接已关闭")}}eventSource.onopen = function (){console.log("连接已打开")}
</script>
</body>
</html>
package com.cj.sse;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import java.io.IOException;
import java.util.Map;
import java.util.concurrent.*;@Service
@Slf4j
public class SseService {
// 存监听器,,Map<String, SseEmitter> sseCache = new ConcurrentHashMap<>();public SseEmitter connect(String clientId) {SseEmitter sseEmitter = new SseEmitter(0L);ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);// 30秒一次,延迟0秒开始scheduler.scheduleAtFixedRate(()->{// 创建了一个新的事件,,名字是message,发送heartbeattry {sseEmitter.send(SseEmitter.event().name("message").data("Heartbeat"));} catch (IOException e) {throw new RuntimeException(e);}},0,30, TimeUnit.MINUTES);sseCache.put(clientId,sseEmitter);System.out.println(sseCache+"---"+sseCache.size());return sseEmitter;}/*** 发送消息 : 发送给指定的Emitter,也可以是所有*/public void sendMessageToAll(String message){try {log.info("发送消息all:{}",message);for (SseEmitter emitter : sseCache.values()) {emitter.send(message);}} catch (IOException e) {log.error("发送消息失败",e);}}/*** 打开页面的时候 监听,,,, 离开页面的时候,移除监听* @param userId*/public void closeSse(String userId){if (sseCache.containsKey(userId)){SseEmitter sseEmitter = sseCache.get(userId);sseEmitter.complete();sseCache.remove(userId);}else{log.info("用户{} 已关闭",userId);}}
}