SpringBoot 使用WebSocket打造在线聊天室(基于注解)

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> SpringBoot 使用WebSocket打造在线聊天室(基于注解)

点击上方“好好学java”,选择“置顶公众号”

优秀学习资源、干货第一时间送达!

 精彩内容 

一、打造 WebSocket 聊天客户端

温馨提示:得益于W3C国际标准的实现,我们在浏览器JS就能直接创建WebSocket对象,再通过简单的回调函数就能完成WebSocket客户端的编写,非常简单!接下来让我们一探究竟。

使用说明

使用步骤:1、获取WebSocket客户端对象。

例如: var webSocket = new WebSocket(url);

使用步骤:2、获取WebSocket回调函数。

例如: webSocket.onmessage = function (event) {console.log('WebSocket收到消息:' + event.data);

|事件类型|WebSocket回调函数事件描述
|——
|open|webSocket.onopen当打开连接后触发
|message|webSocket.onmessage当客户端接收服务端数据时触发
|error|webSocket.onerror当通信异常时触发
|close|webSocket.onclose当连接关闭时触发

使用步骤:3、发送消息给服务端

例如: webSokcet.send(jsonStr)结合实际场景 本案例采用JSON字符串进行消息通信。

具体实现

下面是本案例在线聊天的客户端实现的JS代码,附带详细注释。


<script>

    /**
     * WebSocket客户端
     *
     * 使用说明:
     * 1、WebSocket客户端通过回调函数来接收服务端消息。例如:webSocket.onmessage
     * 2、WebSocket客户端通过send方法来发送消息给服务端。例如:webSocket.send();
     */
    function getWebSocket() {
        /**
         * WebSocket客户端 PS:URL开头表示WebSocket协议 中间是域名端口 结尾是服务端映射地址
         */
        var webSocket = new WebSocket('ws://localhost:8080/chat');
        /**
         * 当服务端打开连接
         */
        webSocket.onopen = function (event) {
            console.log('WebSocket打开连接');
        };

        /**
         * 当服务端发来消息:1.广播消息 2.更新在线人数
         */
        webSocket.onmessage = function (event) {
            console.log('WebSocket收到消息:%c' + event.data, 'color:green');
            //获取服务端消息
            var message = JSON.parse(event.data) || {};
            var $messageContainer = $('.message-container');
            //喉咙发炎
            if (message.type === 'SPEAK') {
                $messageContainer.append(
                    '<div class="mdui-card" style="margin: 10px 0;">' +
                    '<div class="mdui-card-primary">' +
                    '<div class="mdui-card-content message-content">' + message.username + ":" + message.msg + '</div>' +
                    '</div></div>');
            }
            $('.chat-num').text(message.onlineCount);
            //防止刷屏
            var $cards = $messageContainer.children('.mdui-card:visible').toArray();
            if ($cards.length > 5) {
                $cards.forEach(function (item, index) {
                    index < $cards.length - 5 && $(item).slideUp('fast');
                });
            }
        };

        /**
         * 关闭连接
         */
        webSocket.onclose = function (event) {
            console.log('WebSocket关闭连接');
        };

        /**
         * 通信失败
         */
        webSocket.onerror = function (event) {
            console.log('WebSocket发生异常');

        };
        return webSocket;
    }

    var webSocket = getWebSocket();

    /**
     * 通过WebSocket对象发送消息给服务端
     */
    function sendMsgToServer() {
        var $message = $('#msg');
        if ($message.val()) {
            webSocket.send(JSON.stringify({username: $('#username').text(), msg: $message.val()}));
            $message.val(null);
        }

    }
    /**
     * 清屏
     */
    function clearMsg(){
      $(".message-container").empty();
    }

    /**
     * 使用ENTER发送消息
     */
    document.onkeydown = function (event) {
        var e = event || window.event || arguments.callee.caller.arguments[0];
        e.keyCode === 13 && sendMsgToServer();
    };
</script>

二、打造 WebSocket 聊天服务端

温馨提示:得益于SpringBoot提供的自动配置,我们只需要通过简单注解 @ServerEndpoint就就能创建WebSocket服务端,再通过简单的回调函数就能完成WebSocket服务端的编写,比起客户端的使用同样非常简单!

使用说明:

首先在POM文件引入 spring-boot-starter-websocket 、thymeleaf 、FastJson等依赖。

使用步骤:1、开启WebSocket服务端的自动注册。

这里需要特别提醒: ServerEndpointExporter 是由Spring官方提供的标准实现,用于扫描ServerEndpointConfig配置类和@ServerEndpoint注解实例。

使用规则也很简单:1.如果使用默认的嵌入式容器 比如Tomcat 则必须手工在上下文提供ServerEndpointExporter。

  1. 如果使用外部容器部署war包,则不要提供提供ServerEndpointExporter,因为此时SpringBoot默认将扫描服务端的行为交给外部容器处理。
    ```
    @Configuration
    public class WebSocketConfig {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {

        return new ServerEndpointExporter();
    }
}



#### 使用步骤:2、创建WebSocket服务端。

核心思路:
- ① 通过注解`@ServerEndpoint`来声明实例化WebSocket服务端。- ② 通过注解`@OnOpen@OnMessage@OnClose@OnError` 来声明回调函数。
|事件类型|WebSocket服务端注解<th width="166">事件描述</th>
|------
|open|@OnOpen<td width="166">当打开连接后触发</td>
|message|@OnMessage<td width="166">当客户端接收服务端数据时触发</td>
|error|@OnClose<td width="146">当通信异常时触发</td>
|close|@OnError<td width="146">当连接关闭时触发</td>
- ③ 通过`ConcurrentHashMap`保存全部在线会话对象。

@Component
@ServerEndpoint(“/chat”)//标记此类为服务端
public class WebSocketChatServer {

    /**
     * 全部在线会话  PS: 基于场景考虑 这里使用线程安全的Map存储会话对象。
     */
    private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();

    /**
     * 当客户端打开连接:1.添加会话对象 2.更新在线人数
     */
    @OnOpen
    public void onOpen(Session session) {
        onlineSessions.put(session.getId(), session);
        sendMessageToAll(Message.jsonStr(Message.ENTER, “”, “”, onlineSessions.size()));
    }

    /**
     * 当客户端发送消息:1.获取它的用户名和消息 2.发送消息给所有人
     * <p>
     * PS: 这里约定传递的消息为JSON字符串 方便传递更多参数!
     */
    @OnMessage
    public void onMessage(Session session, String jsonStr) {
        Message message = JSON.parseObject(jsonStr, Message.class);
        sendMessageToAll(Message.jsonStr(Message.SPEAK, message.getUsername(), message.getMsg(), onlineSessions.size()));
    }

    /**
     * 当关闭连接:1.移除会话对象 2.更新在线人数
     */
    @OnClose
    public void onClose(Session session) {
        onlineSessions.remove(session.getId());
        sendMessageToAll(Message.jsonStr(Message.QUIT, “”, “下线了!”, onlineSessions.size()));
    }

    /**
     * 当通信发生异常:打印错误日志
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 公共方法:发送信息给所有人
     */
    private static void sendMessageToAll(String msg) {
        onlineSessions.forEach((id, session) -> {
            try {
                session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

}


- ④ 通过会话对象 `javax.websocket.Session` 来发消息给客户端。

/**
 * WebSocket 聊天消息类
 */
@AllArgsConstructor
@Data
public class Message {

    public static final String ENTER = “ENTER”;
    public static final String SPEAK = “SPEAK”;
    public static final String QUIT = “QUIT”;

    private String type;//消息类型

    private String username; //发送人

    private String msg; //发送消息

    private int onlineCount; //在线用户数

    public static String jsonStr(String type, String username, String msg, int onlineTotal) {
        return JSON.toJSONString(new Message(type, username, msg, onlineTotal));
    }ws-gif.gif

}

```

三、WebSocket在线聊天案例的视频演示

1、源码下载

至此,我们完成了客户端和服务端的编码,由于篇幅有限,本教程的页面代码并未完整贴上,想要完整的体验效果请在Github下载源码。传送门:https://github.com/yizhiwazi/springboot-socks/tree/master/springboot-websocket-chat

2、视频演示

上面一顿操作猛如虎,实际到底是啥样子呢,接下来由哈士奇童鞋为我们演示最终版的在线聊天案例:

四、全文总结

1、使用WebSocket用于实时双向通讯的场景,常见的如聊天室、跨系统消息推送等。

2、创建WebSocket客户端使用JS内置对象+回调函数+send方法发送消息。

3、创建WebSocket服务端使用注解声明实例+使用注解声明回调方法+使用Session发送消息。

作者:yizhiwazi出处:https://www.jianshu.com/p/55cfc9fcb69e

阅****读

1. 

****2. ****

3. 

4.**** ****

附上热门QQ群,存放资源和历史资料,2000容量(低门槛付费群),长按二维码入群

原文地址:https://sihai.blog.csdn.net/article/details/109464857

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> SpringBoot 使用WebSocket打造在线聊天室(基于注解)


 上一篇
C连接MySQL数据库开发之Windows环境配置及测试 C连接MySQL数据库开发之Windows环境配置及测试
#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;windows.h&gt; #include &lt;
2021-04-04
下一篇 
ubuntu14.04、CentOS安装oracle 11g数据库【转载】 ubuntu14.04、CentOS安装oracle 11g数据库【转载】
出处:ubuntu14.04、CentOS安装oracle 11g数据库 折腾了好久才装成功,之前打算在虚拟机里边装oracle,但是虚拟机的硬盘空间用完了,所以就用之前在阿里买的服务器上安装oracle,服务器是Ubuntu14.04版
2021-04-04