程序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/

  

  

  

 

 posted on 2022-08-19 14:14  曹军  阅读(212)  评论(0编辑  收藏  举报