SpringBoot + WebSocket实现简单的在线聊天应用

SpringBoot + WebSocket实现简单的在线聊天应用

  •  10个月前
  •  627
  •  Java SpringBoot WebSocket 

介绍

WebSocket协议是基于TCP的一种新的网络协议。该协议提供了通过一个套接字实现全双工通信的功能,全双工意味着服务器可以发送给浏览器,浏览器也可以发送给服务器。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

如果我们想实现一个简单的聊天应用的话,在没有WebSocket的时候一般会选择Ajax轮询的方式,从服务器拉取消息。这种方式虽然能实现我们的需求但是显得非常笨拙,同时由于不停的轮询给服务器造成很大的压力。而WebSocket在浏览器和服务器建立连接之后,任何一方都可以主动发起通信。

下面开始介绍如何在SpringBoot中整合WebSocket

Maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

配置

@Configuration
@EnableWebSocket
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

Server

@Controller
@ServerEndpoint("/ws")
public class WebSocketServer {

    private static CopyOnWriteArraySet<Session> sessions = new CopyOnWriteArraySet<>();

    @OnOpen
    public void onOpen(Session session) {
        System.out.println("socket open .");
        sessions.add(session);
        this.broadcast("[用户" + session.getId() + "]加入聊天室.");
        System.out.println("size:" + sessions.size());
    }

    @OnClose
    public void onClose(Session session) {
        sessions.remove(session);
        this.broadcast("[用户" + session.getId() + "]退出聊天室.");
        System.out.println("size:" + sessions.size());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(session.getId() + " say " + message);
        this.broadcast("[用户" + session.getId() + "]说:" + message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        sessions.remove(session);
        error.printStackTrace();
    }

    private void broadcast(String message) {
        sessions.forEach(session -> sendMessage(session, message));
    }

    private void sendMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Client

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
    <script type="text/javascript">
        let webSocket = null;

        if ('WebSocket' in window) {
            webSocket = new WebSocket("ws://127.0.0.1:9002/ws");
        } else {
            console.log('webSocket not support')
        }

        webSocket.onopen = function () {
            show("已连接");
        };

        webSocket.onmessage = function (event) {
            $('#message').append('<div class="ms">' + event.data + '</div>')
        };

        webSocket.onclose = function () {
            show("已关闭");
        };

        webSocket.onerror = function () {
            show("连接错误");
        };

        function closeWebSocket() {
            webSocket.close();
        }

        function show(innerHTML) {
            document.getElementById('status').innerHTML = innerHTML;
        }

        function send() {
            let message = document.getElementById('ta').value;
            webSocket.send(message);
            document.getElementById('ta').value = '';
        }

        window.onbeforeunload = function () {
            webSocket.close();
        };

    </script>

</head>
<body>
<div class="container" style="padding: 20px">
    <div class="status">
        连接状态:<span id="status">未连接</span>
        <a href="javascript:void(0)" onclick="closeWebSocket()">关闭连接</a>
    </div>
    <hr>
    <div id="message" style="min-height: 200px; margin: 20px 0 10px">

    </div>
    <hr>
    <div class="text">
        <textarea name="" id="ta" cols="60" rows="4"></textarea>
        <br>
        <button onclick="send()">发送</button>
    </div>
</div>
</body>
</html>

效果


源码地址

https://github.com/chenpeidong/spring-boot-demo

扫一扫分享到微信

已有 条评论
写评论