0


SpringBoot整合WebSocket(看完即入门)

WebSocket

1、什么是webSocket?

WebSocket是一种在单个

**TCP连接**

上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,

允许服务端主动向客户端推送数据

。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以

创建持久性的连接,并进行双向数据传输。

在这里插入图片描述

2、webSocket可以用来做什么?

利用双向数据传输的特点可以用来完成很多功能,不需要前端

轮询

,浪费资源。例如:

1、通告功能
2、聊天功能 (如下是逻辑图)
在这里插入图片描述
3、实时更新数据功能
4、弹幕

3、webSocket协议

本协议有两部分:握手和数据传输。
握手是基于http协议的。

GETws://localhost/chat HTTP/1.1Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version:13

来自服务器的握手看起来像如下形式:

HTTP/1.1101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

在这里插入图片描述

4、服务端

maven依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId><version>5.7.22</version></dependency>

WebSocket配置类

importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.socket.server.standard.ServerEndpointExporter;/**
 * @author Hao
 * @date 2023-03-01 16:18
 * @description:
 * @version:
 */@ConfigurationpublicclassWebSocketConfig{/**
     *     注入ServerEndpointExporter,
     *     这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */@BeanpublicServerEndpointExporterserverEndpointExporter(){returnnewServerEndpointExporter();}}

WebSocket操作类

通过该类WebSocket可以进行群推送以及单点推送

importorg.apache.logging.log4j.LogManager;importorg.apache.logging.log4j.Logger;importorg.springframework.stereotype.Component;importcn.hutool.core.util.StrUtil;importjavax.websocket.*;importjavax.websocket.server.PathParam;importjavax.websocket.server.ServerEndpoint;importjava.io.IOException;importjava.util.concurrent.ConcurrentHashMap;/**
 * @author Hao
 * @date 2023-03-01 16:18
 * @description:
 * @version:
 */@ServerEndpoint(value ="/websocket/{userId}")@ComponentpublicclassWebSocket{privatefinalstaticLogger logger =LogManager.getLogger(WebSocket.class);/**
     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的
     */privatestaticint onlineCount =0;/**
     * concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象
     */privatestaticConcurrentHashMap<String,WebSocket> webSocketMap =newConcurrentHashMap<>();/**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */privateSession session;privateString userId;/**
     * 连接建立成功调用的方法
     */@OnOpenpublicvoidonOpen(Session session,@PathParam("userId")String userId){this.session = session;this.userId = userId;//加入map
        webSocketMap.put(userId,this);addOnlineCount();//在线数加1
        logger.info("用户{}连接成功,当前在线人数为{}", userId,getOnlineCount());try{sendMessage(String.valueOf(this.session.getQueryString()));}catch(IOException e){
            logger.error("IO异常");}}/**
     * 连接关闭调用的方法
     */@OnClosepublicvoidonClose(){//从map中删除
        webSocketMap.remove(userId);subOnlineCount();//在线数减1
        logger.info("用户{}关闭连接!当前在线人数为{}", userId,getOnlineCount());}/**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */@OnMessagepublicvoidonMessage(String message,Session session){
        logger.info("来自客户端用户:{} 消息:{}",userId, message);//群发消息/*for (String item : webSocketMap.keySet()) {
            try {
                webSocketMap.get(item).sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }*/}/**
     * 发生错误时调用
     *
     * @OnError
     */@OnErrorpublicvoidonError(Session session,Throwable error){
        logger.error("用户错误:"+this.userId +",原因:"+ error.getMessage());
        error.printStackTrace();}/**
     * 向客户端发送消息
     */publicvoidsendMessage(String message)throwsIOException{this.session.getBasicRemote().sendText(message);//this.session.getAsyncRemote().sendText(message);}/**
     * 通过userId向客户端发送消息
     */publicvoidsendMessageByUserId(String userId,String message)throwsIOException{
        logger.info("服务端发送消息到{},消息:{}",userId,message);if(StrUtil.isNotBlank(userId)&&webSocketMap.containsKey(userId)){
         webSocketMap.get(userId).sendMessage(message);}else{
         logger.error("用户{}不在线",userId);}}/**
     * 群发自定义消息
     */publicstaticvoidsendInfo(String message)throwsIOException{for(String item : webSocketMap.keySet()){try{
                webSocketMap.get(item).sendMessage(message);}catch(IOException e){continue;}}}publicstaticsynchronizedintgetOnlineCount(){return onlineCount;}publicstaticsynchronizedvoidaddOnlineCount(){WebSocket.onlineCount++;}publicstaticsynchronizedvoidsubOnlineCount(){WebSocket.onlineCount--;}}

测试controller

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjava.io.IOException;/**
 * @author Hao
 * @date 2023-03-01 16:18
 * @description:
 * @version:
 */@RestController@RequestMapping("/webSocket")publicclassWebSocketController{@AutowiredprivateWebSocket webSocket;@PostMapping("/sentMessage")publicvoidsentMessage(String userId,String message){try{
            webSocket.sendMessageByUserId(userId,message);}catch(IOException e){
            e.printStackTrace();}}}

5、webSocket网页客户端工具

http://websocket.jsonin.com/

在这里插入图片描述
复制三个tab

WebSocket地址分别输入后连接

ws://127.0.0.1:8051/websocket/1
ws://127.0.0.1:8051/websocket/2
ws://127.0.0.1:8051/websocket/3

在这里插入图片描述

通讯测试

1.往客户端发消息

127.0.0.1:8092/webSocket/sentMessage?userId=1&message=请进入视频会议
127.0.0.1:8092/webSocket/sentMessage?userId=2&message=请进入视频会议
127.0.0.1:8092/webSocket/sentMessage?userId=3&message=请进入视频会议

在这里插入图片描述

在这里插入图片描述

2.客户端收到消息回复“好的”
在这里插入图片描述

最后送所有正在努力的大家一句话:

你不一定逆风翻盘,但一定要向阳而生。

期待下次发布好的文章:

山水相逢,我们江湖见。


本文转载自: https://blog.csdn.net/heima005/article/details/129285102
版权归原作者 江東-H 所有, 如有侵权,请联系我们删除。

“SpringBoot整合WebSocket(看完即入门)”的评论:

还没有评论