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的,感觉不能用,或者对我这个不起作用,只能用自己的前端。

 

posted @ 2020-11-16 19:03  忧伤还是快乐EL  阅读(239)  评论(0编辑  收藏  举报