程序git:https://gitee.com/juncaoit/websocketpro
1.引入pom
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
2.@ServerEndpoint
@ServerEndpoint
注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
/** * 会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint * 要注意,如果使用独立的servlet容器, * 而不是直接使用springboot的内置容器, * 就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。 */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }
3.服务器方法
package com.jun.send.websocket; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; @Component @Slf4j @ServerEndpoint("/webSocket/{category}") public class WebSocketServer { /** * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 */ private static int onlineCount = 0; /** * concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。 */ public static ConcurrentHashMap<WebSocketServer, String> webSocketMap = new ConcurrentHashMap<>(); /** * 与某个客户端的连接会话,需要通过它来给客户端发送数据 */ private Session session; /** * 连接建立成 * 功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("category") String category) { this.session = session; webSocketMap.put(this, category); log.info("【websocket消息】有新的连接,总数:{}", webSocketMap.size()); sendInfo("连接成功"); } /** * 连接关闭 * 调用的方法 */ @OnClose public void onClose() { webSocketMap.remove(this); log.info("【websocket消息】连接断开,总数:{}", webSocketMap.size()); } /** * 收到客户端消 * 息后调用的方法 * * @param message 客户端发送过来的消息 **/ @OnMessage public void onMessage(String message) { log.info("【websocket消息】收到客户端发来的消息:{}", message); } /** * @param error */ @OnError public void onError(Throwable error) { log.error("发和错误,原因:" + error.getMessage()); error.printStackTrace(); } /** * 实现服务 * 器主动推送 */ public void sendMessage(String message, String category) { for (Map.Entry<WebSocketServer, String> entry : webSocketMap.entrySet()) { WebSocketServer webSocketServer = entry.getKey(); log.info("【websocket消息】广播消息,category={}, message={}", category, message); try { webSocketServer.session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } /** * 发送自定 * 义消息 **/ public void sendInfo(String message) { try { this.session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } }
4.job定时推送给前端数据
package com.jun.send.job; import com.alibaba.fastjson.JSON; import com.jun.send.model.WpDataInfo; import com.jun.send.websocket.WebSocketServer; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Date; import java.util.concurrent.ConcurrentHashMap; @Slf4j @Service public class SendMessageJob { @Resource private WebSocketServer webSocketServer; @Scheduled(cron = "0 */2 * * * ?") public void sendMessage() { ConcurrentHashMap<WebSocketServer, String> webSocketMap = WebSocketServer.webSocketMap; if (webSocketMap.size() <= 0) { log.info("没有session,不进行处理,不进行推送数据"); return; } WpDataInfo wpDataInfo = new WpDataInfo(); wpDataInfo.setDeviceNo("34-ME-01"); wpDataInfo.setCreateTime("2022-08-17 00:00:00"); webSocketServer.sendMessage(JSON.toJSONString(wpDataInfo), "wp"); log.info("发送的数据成功"); } }
5.前端代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebSocket client</title> <script type="text/javascript"> var socket; if (typeof (WebSocket) == "undefined"){ alert("This explorer don't support WebSocket") } function connect() { //Connect WebSocket server socket =new WebSocket("ws://127.0.0.1:8099/webSocket/wp"); //open socket.onopen = function () { alert("WebSocket is open"); } //Get message socket.onmessage = function (msg) { alert("Message is " + msg); } //close socket.onclose = function () { alert("WebSocket is closed"); } //error socket.onerror = function (e) { alert("Error is " + e); } } function close() { socket.close(); } function sendMsg() { socket.send("This is a client message "); } </script> </head> <body> <button onclick="connect()">connect</button> <button onclick="close()">close</button> <button onclick="sendMsg()">sendMsg</button> </body> </html>
6.测试
问题:
1.这里往所有的websocket中发送消息了,需要添加一下判断。
2.可以使用提供的工具类进行测试
http://www.jsons.cn/websocket/