SpringBoot集成WebSocket实现在线聊天

这篇具有很好参考价值的文章主要介绍了SpringBoot集成WebSocket实现在线聊天。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在项目过程中涉及到了在线聊天的业务,刚好有了解到WebSocket可以实现这一功能,因此便对其进行了一定的研究并做下笔记,在本文中主要借鉴了以下资源:

  • WebSocket_百度百科
  • 李士伟的小程序聊天工程
  • Springboot+Websocket中@Autowired注入service为null的解决方法

1、WebSocket引入

WebSocket是HTML5规范中的一个部分,它借鉴了socket这种思想,为web应用程序客户端和服务端之间提供了一种全双工通信机制。同时,它又是一种新的应用层协议,WebSocket协议是为了提供web应用程序和服务端全双工通信而专门制定的一种应用层协议,其基于TCP传输协议,并复用了HTTP的握手通道。通常它表示为:ws://echo.websocket.org/?encoding=text HTTP/1.1,可以看到除了前面的协议名和http不同之外,它的表示地址就是传统的url地址。

SpringBoot集成WebSocket实现在线聊天

WebSocket的优点主要如下:

  1. 支持双向通信,实时性更强
  2. 更好的二进制支持
  3. 较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部。
  4. 支持扩展。ws协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)
  5. 更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。

2、环境搭配

2.1、工程创建


这里的话狗子我创建的是一个简单的SpringBoot工程,内含了Lombok、fastjson等基础依赖,这一块大家自行发挥即可。

2.2、依赖导入


这里需要导入一个Spring家对WebSocket的依赖包,方便后续的配置。

<!--websocket-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>5.3.9</version>
</dependency>

2.3、配置类


通过配置类往容器中注入ServerEndpointExporter从而开启WebSocket支持

@Configuration
public class WebSocketConfig {

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

3、具体实现

3.1、前置知识


在WebSocket中存在各种触发事件,在Java中这些事件对应着不同的注解,从而对不同事件的逻辑进行自定义操作。

事件 对应注解 描述
open @OnOpen 连接建立时触发
message @OnMessage 客户端接收服务端数据时触发
close @OnClose 连接关闭时触发
error @OnError 通信发生错误时触发

注意:下方提及到的IM为即时通讯Instant Messaging

3.2、数据封装


在WebSocket中主要通过Session进行通讯,注意的是这里的Session并不是我们平时所说的RequestSession,而是javax.websocket包下的Session。而同时还需要一个通讯标识标识不同人之间的通讯连接。如:

  • A和B连接通讯的通讯标识为abcd
  • A和C连接通讯的通讯标识为qwer
  • B和A连接通讯的通讯标识为abcd
@Data
public class WebSocketData {
    /**
     * 当前连接
     */
    private Session session;
    /**
     * 当前通讯ID
     */
    private String communicationId;
}

3.3、思路分析


SpringBoot集成WebSocket实现在线聊天

3.4、服务构建


在项目中创建server包,并在该包下新建IMServer.java文件,用于编写具体IM的逻辑,其中包含以下属性配合实现具体的通讯逻辑。

@RestController
@Slf4j
@ServerEndpoint(value = "/im/{senderId}/{communicationId}")
public class IMServer {
    /**
     * 记录在线连接
     */
    public static final Map<String, WebSocketData> sessionMap = new ConcurrentHashMap<>();

    /**
     * 封装一个sessionData的类,内含通讯标识和session对象
     */
    private final WebSocketData webSocketData = new WebSocketData();

    /**
     * 用于后续信息存入数据库中使用
     */
    private static MessageService messageService;
    
    @Autowired
    public void setMessageService(MessageService messageService) {
        IMServer.messageService = messageService;
    }
    
    /**
     * @description 获取当前在线人数
     * @method getOnlineCount
     * @author xbaozi
     * @date 2022/9/26 17:11
     **/
    private static synchronized int getOnlineCount() {
        return sessionMap.size();
    }
}

3.5、连接建立


/**
 * @param session  与某个客户端的连接会话
 * @param senderId 建立连接的用户
 * @description 连接建立成功调用的方法
 * @method onOpen
 * @author xbaozi
 * @date 2022/9/25 23:05
 **/
@OnOpen
public void onOpen(Session session, @PathParam("senderId") String senderId, @PathParam("communicationId") String communicationId) {
    webSocketData.setSession(session);
    webSocketData.setCommunicationId(communicationId);
    sessionMap.put(senderId, webSocketData);
    log.info("{}: 开始创建连接,新用户{}加入,当前在线人数{}", session, senderId, getOnlineCount());
}

3.6、消息通讯


/** 
 * @description 收到客户端消息后调用的方法
 * @method onMessage
 * @author xbaozi 
 * @date 2022/9/27 16:25 
 * @param message   收到的消息
 * @param senderId  发送者ID
 **/
@OnMessage
public void onMessage(String message, @PathParam("senderId") String senderId) {
    WebSocketData senderWebSocketData = sessionMap.get(senderId);
    // 判断发送者连接
    if (senderWebSocketData.getSession() != null) {
        log.info("收到的消息为{}", message);
        // 数据处理
        Message messageObject = JSON.parseObject(message, Message.class);
        log.info("转换成message实体为{}", messageObject);
        try {
            // 发送消息
            sendMessage(senderWebSocketData, messageObject);
        } catch (IOException e) {
            log.info("发送失败,传输出现问题");
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    } else {
        log.info("发送失败,未找到用户userId={}的session", senderId);
    }

}

/**
 * @param senderWebSocketData 内部封装了当前连接信息
 * @param messageObject       需要发送的消息实体
 * @description 发送数据
 * @method sendMessage
 * @author xbaozi
 * @date 2022/9/27 16:22
 **/
private void sendMessage(WebSocketData senderWebSocketData, Message messageObject) throws IOException {
    Session senderSession = senderWebSocketData.getSession();
    if (messageObject == null) {
        // 数据异常,提醒发送者
        senderSession.getBasicRemote().sendText(JSON.toJSONString(Result.error(MISSING_REQUEST_PARAM)));
    } else {
        // 数据写入数据库
        messageObject.setMessageId(UUID.randomUUID().toString(true));
        boolean isSuccess = messageService.save(messageObject);
        if (BooleanUtil.isFalse(isSuccess)) {
            messageObject.setMessageStatus(MESSAGE_STATUS_EXCEPTION);
        }
        // 尝试获取接收者连接
        WebSocketData receiverWebSocketData = sessionMap.get(messageObject.getMessageReceiver());
        // 接收者处于在线状态
        if (receiverWebSocketData.getSession() != null) {
            // 判断当前连接是否为当前通话创建的连接,设置消息为已读
            if (receiverWebSocketData.getCommunicationId().equals(senderWebSocketData.getCommunicationId())) {
                messageObject.setMessageReadFlag(HAS_BEEN_READ);
            }
        }
        // 更新通讯时间
        communicationService.update(new LambdaUpdateWrapper<Communication>()
                .set(Communication::getCommunicationUpdateTime, new Date())
                .eq(Communication::getCommunicationId, senderWebSocketData.getCommunicationId())
        );
        senderSession.getBasicRemote().sendText(JSONUtil.toJsonStr(messageObject));
    }
}

3.7、连接关闭


/**
 * @description 连接关闭调用的方法
 * @method onClose
 * @author xbaozi
 * @date 2022/9/25 23:10
 **/
@OnClose
public void onClose(@PathParam("senderId") String senderId) {
    sessionMap.remove(senderId);
    log.info("用户{}连接断开,在线用户{}人……", senderId, getOnlineCount());
}

3.8、连接异常


/**
 * @param exception 捕获到的异常
 * @description 发生错误时调用
 * @method onError
 * @author xbaozi
 * @date 2022/9/25 23:11
 **/
@OnError
public void onError(Throwable exception) {
    log.info("发起连接发生了不可描述的错误……");
    exception.printStackTrace();
}

4、结果演示

由于狗子我只是个卑微的后端小菜鸡,所以就没有写前端代码进行测试。这里感谢李士伟开源的demo工程小程序聊天,内含了小程序端的代码,因此这里直接对代码进行修改引用了我的WebSocket服务。在这里我还跑了工程中的后端项目,用作获取联系人等功能,主要展示的就是发送消息和接受到的消息。

SpringBoot集成WebSocket实现在线聊天文章来源地址https://www.toymoban.com/news/detail-444477.html

到了这里,关于SpringBoot集成WebSocket实现在线聊天的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在线聊天室(Vue+Springboot+WebSocket)

    实现了一个简单的在线聊天室的前后端。前端用Vue实现,后端用Springboot实现。         在线聊天室的功能包括创建用户和显示在线用户列表、发送消息和显示消息列表、用户和消息列表实时更新这几点。以下是整体功能的活动图: 用户身份         进入聊天室的用户需

    2024年01月15日
    浏览(52)
  • 基于SpringBoot+Vue+WebSocket的在线聊天室

    WebSocket 是一种在 Web 应用程序中实现双向通信的协议。它提供了一种持久连接,允许客户端和服务器之间进行实时数据传输,而无需进行频繁的请求和响应。 相对于传统的 HTTP 请求-响应模式,WebSocket 在客户端和服务器之间建立起一条长久的双向通信通道。这意味着服务器可

    2024年01月16日
    浏览(72)
  • WebSocket协议理解并实现在线聊天

    写在前面 WebSocket 简称 ws 本文通过介绍ws,然后一步步的使用ws协议进行前后端开发测试,最后使用 SpringBoot 和 vue 利用ws协议达实现一个在线聊天室的小demo(源码在文章末尾)。 看完此篇后将能够完成这样的小demo (需要会使用springboot和vue2以及element-ui) WebSocket是在 HTML5 开

    2024年02月04日
    浏览(35)
  • 毕业设计——基于springboot的在线聊天系统设计与实现

    完整项目地址:https://download.csdn.net/download/lijunhcn/88430400 本项目是一套聊天系统,包括前台手机界面及后台分布式系统,基于SpringBoot+Netty+MUI+H5Plus+Nginx+FastDFS分布式文件系统搭建的聊天系统。 前端聊天系统包含首页门户登录注册、互信、通讯录、发现、我等模块,添加了扫一

    2024年02月03日
    浏览(46)
  • 微信小程序 WebSocket 通信 —— 在线聊天

             * 源码已经上传到资源处,需要的话点击跳转下载 |  源码下载         在Node栏目就讲到了Socket通信的内容,使用Node实现Socke通信,还使用两个流行的WebSocket 库,ws 和 socket.io,在小程序中的WebSocket接口和HTML5的WebSocket基本相同,可以实现浏览器与服务器之间的

    2024年02月01日
    浏览(50)
  • 基于WebSocket的在线文字聊天室

    与Ajax不同,WebSocket可以使服务端主动向客户发送响应,本案例就是基于WebSocket的一个在线聊天室,不过功能比较简单,只能满足文字交流。演示如下。 案例学习于b站up主,链接 。这位up主讲的非常清楚,值得去学习。本文属于记录自我学习过程的文章。 项目目录下app.js 项

    2024年02月13日
    浏览(63)
  • Gin+WebSocket实战——在线聊天室WebSocketDemo详细使用教程

    Github:https://github.com/palp1tate/WebsocketDemo 欢迎star!😎 利用 Gin + WebSocket 实现的在线聊天室 Demo 项目,支持加入/离开聊天室广播、给其他用户发送消息等。 进入项目根目录,执行命令 go run . 命令,结果如下: 可以看到们的 HTTP 服务已经启动成功并运行在了 8080 端口上。 接下

    2024年04月26日
    浏览(74)
  • 巧妙利用java实现在线聊天系统教程方法

    一、搭建服务器端 a)、创建ServerSocket对象绑定监听端口。 b)、通过accept()方法监听客户端的请求。 c)、建立连接后,通过输入输出流读取客户端发送的请求信息。 d)、通过输出流向客户端发送请求信息。 e)、关闭相关资源。 二、搭建客户器端 a)、创建Socket对象,指明需要连接

    2024年02月08日
    浏览(89)
  • WPF+ASP.NET SignalR实现简易在线聊天功能

    在实际业务中,当后台数据发生变化,客户端能够实时的收到通知,而不是由用户主动的进行页面刷新才能查看,这将是一个非常人性化的设计。有没有那么一种场景,后台数据明明已经发生变化了,前台却因为没有及时刷新,而导致页面显示的数据与实际存在差异,从而造

    2024年02月07日
    浏览(44)
  • C语言实现--基于UDP的多人在线聊天室

    目录 实现功能 实现思想 实现代码(部分及详解) 服务端部分代码 客户端部分代码 实现效果 项目中出现的问题和解决方法 项目整体代码展示 代码优化思路 服务端代码 客户端代码 服务端可以同时连接多个客户端; 新的客户端连接服务端时,可以在服务端显示自己的名字并

    2024年02月04日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包