赞
踩
WebSocket是一种在单个TCP连接上进行全双工通信的协议。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
WebSocket只需要完成一次握手就能完成数据的双向传递,这种方式极为方便我们去做定时的查询,例如我们在前端收到用户支付过后,后台页面需要做出相应的语音提醒和信息弹窗去提示我们后台管理人员
- <!--websocket-->
- <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;
-
- /**
- * 开启WebSocket支持
- */
- @Configuration
- public class WebSocketConfig {
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
- }
这个类主要用于使用创建连接、监听消息和发送消息等
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
-
- import javax.websocket.*;
- import javax.websocket.server.PathParam;
- import javax.websocket.server.ServerEndpoint;
- import java.io.IOException;
- import java.util.concurrent.CopyOnWriteArraySet;
-
- // @ServerEndpoint 声明并创建了webSocket端点, 并且指明了请求路径
- // id 为客户端请求时携带的参数, 用于服务端区分客户端使用
- @ServerEndpoint("/ws/{sid}")
- @Component
- public class WebSocketServer {
-
- // 日志对象
- private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
-
- // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
- private static int onlineCount = 0;
-
- // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
- private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
- // private static ConcurrentHashMap<String,WebSocketServer> websocketList = new ConcurrentHashMap<>();
-
- // 与某个客户端的连接会话,需要通过它来给客户端发送数据
- private Session session;
-
- // 接收sid
- private String sid = "";
-
- /*
- * 客户端创建连接时触发
- * */
- @OnOpen
- public void onOpen(Session session, @PathParam("sid") String sid) {
- this.session = session;
- webSocketSet.add(this); // 加入set中
- addOnlineCount(); // 在线数加1
- log.info("有新窗口开始监听:" + sid + ", 当前在线人数为" + getOnlineCount());
- this.sid = sid;
- try {
- sendMessage("连接成功");
- } catch (IOException e) {
- log.error("websocket IO异常");
- }
- }
-
- /**
- * 客户端连接关闭时触发
- **/
- @OnClose
- public void onClose() {
- webSocketSet.remove(this); // 从set中删除
- subOnlineCount(); // 在线数减1
- log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
- }
-
- /**
- * 接收到客户端消息时触发
- */
- @OnMessage
- public void onMessage(String message, Session session) {
- log.info("收到来自窗口" + sid + "的信息:" + message);
- // 群发消息
- for (WebSocketServer item : webSocketSet) {
- try {
- item.sendMessage(message);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- /**
- * 连接发生异常时候触发
- */
- @OnError
- public void onError(Session session, Throwable error) {
- log.error("发生错误");
- error.printStackTrace();
- }
-
- /**
- * 实现服务器主动推送(向浏览器发消息)
- */
- public void sendMessage(String message) throws IOException {
- log.info("服务器消息推送:"+message);
- this.session.getBasicRemote().sendText(message);
- }
-
- /**
- * 发送消息到所有客户端
- * 指定sid则向指定客户端发消息
- * 不指定sid则向所有客户端发送消息
- * */
- public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException {
- log.info("推送消息到窗口" + sid + ",推送内容:" + message);
- for (WebSocketServer item : webSocketSet) {
- try {
- // 这里可以设定只推送给这个sid的,为null则全部推送
- if (sid == null) {
- item.sendMessage(message);
- } else if (item.sid.equals(sid)) {
- item.sendMessage(message);
- }
- } catch (IOException e) {
- continue;
- }
- }
- }
-
- public static synchronized int getOnlineCount() {
- return onlineCount;
- }
-
- public static synchronized void addOnlineCount() {
- WebSocketServer.onlineCount++;
- }
-
- public static synchronized void subOnlineCount() {
- WebSocketServer.onlineCount--;
- }
-
- public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
- return webSocketSet;
- }
-
- }
- <div id="wrap" v-show="false">
- <audio v-if="false" src="@/api/audio/preview.mp3" id="audio" preload="auto" muted autoplay type="audio/mp3" controls="controls" >
- <span id="audioId">播放音乐</span>
- </audio>
- </div>
-
-
- created() {
- this.initWebSocket();
- },
- destroyed() {
- this.websock.close() //离开路由之后断开websocket连接
- },
- methods: {
- initWebSocket(){
- const wsuri = "ws://localhost:8080/ws/123214";
- if(typeof(WebSocket) == "undefined") {
- console.log("您的浏览器不支持WebSocket");
- }else{
- console.log(wsuri)
- this.websock = new WebSocket(wsuri);
- this.websock.onmessage = this.websocketonmessage;
- this.websock.onopen = this.websocketonopen;
- this.websock.onerror = this.websocketonerror;
- this.websock.onclose = this.websocketclose;
- }
- },
- //连接建立之后执行send方法发送数据
- websocketonopen(){
- let actions = {"test":"我已在线"};
- this.websocketsend(JSON.stringify(actions));
- },
- //连接建立失败重连
- websocketonerror(){
- this.initWebSocket();
- },
- //数据接收
- websocketonmessage(e){
- this.$modal.msg(e.data);
- console.log(e.data);
- var audio = document.querySelector("audio");//用这种标签名称获取的方式就不会报错了,,,,
- audio.currentTime = 0;//从头开始播放
- audio.muted = false;//取消静音
- audio.play();//音频播放
- // const redata = JSON.parse(e.data);
- },
- //数据发送
- websocketsend(Data){
- this.websock.send(Data);
- },
- //关闭
- websocketclose(e){
- console.log('断开连接',e);
- },
- }
audio是因为业务场景需要引入的,主要是对与来订单提醒的提示音,然后可以在websocketonmessage()接受数据和进行处理
这个主要是方便我们测试
整体结构(仅供参考)
大家可以使用若依的定时任务,去写一下业务逻辑,然后在后台管理的定时任务里面可以去执行一次定时任务,去观察页面和后台日志的变化,给前台发送数据就是调用WebSocketServer类里面的sendInfo()方法,参数第一个是你要发送的消息,第二个是sid就是你建立连接的那个sid
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。