websocket+springboot原生
依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
配置:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * @author scl * date 2020/11/13 0013 17:11 */ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }
真正实现:
import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CopyOnWriteArraySet; /** * author scl * date 2020/11/13 0013 17:16 */ @ServerEndpoint(value = "/web/alarmSocket") @Component public class AlarmSocket { private static final Logger logger = LoggerFactory.getLogger(AlarmSocket.class); /** * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 */ private static int onlineCount = 0; public static CopyOnWriteArraySet<AlarmSocket> webSocketSet = new CopyOnWriteArraySet<AlarmSocket>(); public Session session; @Autowired private AlarmMessageService alarmMessageService; @OnOpen public void open(Session session) { this.session = session; webSocketSet.add(this); onlineCount++; logger.info("当前在线人数为" + getOnlineCount()); try { synchronized (AlarmSocket.class) { sendMessage("连接成功"); } } catch (IOException e) { logger.error("websocket IO异常"); } } private void sendMessage(String message) throws IOException { if (this.session.isOpen()) { this.session.getBasicRemote().sendText(message); } } @OnClose public void onClose(Session session) { //从set中删除 webSocketSet.remove(this); subOnlineCount(); logger.info("有一连接关闭!当前在线人数为" + getOnlineCount()); } @OnError public void onError(Session session, Throwable throwable) { logger.error("发生错误:,{}", throwable.toString()); } @OnMessage public void onMessage(String message, Session session) { logger.info("收到客户端发来的消息: {}", message); for (AlarmSocket item : webSocketSet) { try { synchronized (AlarmSocket.class) { item.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } }
/**
*自测用
*/
@Scheduled(cron = "0/10 * * * * ?") private void sendAll() { long alarmCountNow = alarmMessageService.count(); if (alarmCountNow != alarmCount) { for (AlarmSocket alarmSocket : webSocketSet) { try { map.put("total",alarmCountNow); String s = JSONObject.toJSONString(map); alarmSocket.sendMessage(s); alarmCount++; } catch (IOException e) { e.printStackTrace(); System.out.println("发送失败"); } } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { AlarmSocket.onlineCount++; } public static synchronized void subOnlineCount() { AlarmSocket.onlineCount--; } }
前端:
<!DOCTYPE HTML> <html> <head> <title>WebSocket</title> </head> <body> Welcome<br/> <input id="text" type="text" /><button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button> <div id="message"> </div> </body> <script type="text/javascript"> var websocket = null; //判断当前浏览器是否支持WebSocket if('WebSocket' in window){ websocket = new WebSocket("wss://localhost:8011/web/alarmSocket"); } else{ alert('Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(event){ setMessageInnerHTML("open"); } //接收到消息的回调方法 websocket.onmessage = function(event){ setMessageInnerHTML(event.data); } //连接关闭的回调方法 websocket.onclose = function(){ setMessageInnerHTML("close"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML){ document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //关闭连接 function closeWebSocket(){ websocket.close(); } //发送消息 function send(){ var message = document.getElementById('text').value; websocket.send(message); } </script> </html>
其中:ws和wss的区别:
WebSocket可以使用 ws 或 wss 来作为统一资源标志符,类似于 HTTP 或 HTTPS。其中 ,wss 表示在 TLS 之上的 WebSocket,相当于 HTTPS。默认情况下,WebSocket的 ws 协议基于Http的 80 端口;当运行在TLS之上时,wss 协议默认是基于Http的 443 端口。说白了,wss 就是 ws 基于 SSL 的安全传输,与 HTTPS 一样样的道理。所以,如果你的网站是 HTTPS 协议的,那你就不能使用 ws:// 了,浏览器会 block 掉连接,和 HTTPS 下不允许 HTTP 请求一样。
java.lang.IllegalStateException: The remote endpoint was in state [TEXT_FULL_WRITING] which is an in
解决方法:
加锁。
synchronized (AlarmSocket.class) { sendMessage("连接成功"); }
还有一句想说的,就是不知道为啥,网页上测试websocket的,感觉不能用,或者对我这个不起作用,只能用自己的前端。
我不是来改变世界的