聊天消息实时推送(springBoot,webSocket)

本文介绍如何使用SpringBoot集成WebSocket实现实时消息推送功能,包括代码实现、页面交互及实时推送模拟聊天场景。通过具体实例,展示了WebSocket的连接、消息收发、错误处理和连接关闭等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用springBoot集成的webSocket实现实时消息推送(模仿聊天)

java代码

package com.lsbj.biz.scoket;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

/**
 * @Auther: zs
 * @Date: 2019/1/17 11:04
 * @Description: *
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/ws/push/{userId}")
@Component
public class WebSocketDemo {

    // Hashtablex线程安全的map用来存储一登录用户信息,key为用户id。
    private static Hashtable<String, WebSocketDemo> userMap = new Hashtable<>();

    // 静态变量,用来记录当前在线连接数。
    private static int onlineCount = 0;

    // 与客户端的连接会话。
    private Session session;

    // 与客户端的连接的用户id。
    private String userId;

    //连接打开时执行
    @OnOpen
    public void onOpen(Session session,@PathParam("userId") String userId) throws IOException{
        System.out.println("新客户端接入,用户ID:" + userId);
        System.out.println("在线人数:" + WebSocketDemo.onlineCount);
        if(StringUtils.isNotBlank(userId)){
            this.userId = userId;
            this.session = session;
            userMap.put(userId,this); // 加入set中
            addOnlineCount(); // 在线数加1
        }
        System.out.println("在线人数:" + WebSocketDemo.onlineCount);
    }

    //连接关闭调用的方法
    @OnClose
    public void onClose() {
        System.out.println("客户端关闭连接:"+this.userId);
        userMap.remove(this.userId); // 从map中删除
        subOnlineCount(); // 在线数减1
        System.out.println("在线人数:" + WebSocketDemo.onlineCount);
    }

    //收到客户端消息后调用的方法
    @OnMessage
    public void onMessage(String message, Session session) {
        if(StringUtils.isNotBlank(this.userId)){
            if(!"ping".equals(message)){//不是心跳检测
                //收到消息后可以去做一些具体的业务处理在推送,此处直接推送
                sendAll("【"+this.userId+"】"+message);
            }
        }else{
            System.out.println("当前客户未登陆:"+this.userId);
        }
        System.out.println("用户【"+this.userId+"】访问");
    }

    //发生错误时调用
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    public void sendMessage(String userId,String message){
        try {
            if(!StringUtils.isNotBlank(userId)){
                System.out.println("客户ID不能为空");
                return ;
            }
            for(Map.Entry<String, WebSocketDemo> entry : userMap.entrySet()){
                if(entry.getKey().equals(userId)){
                    entry.getValue().getSession().getBasicRemote().sendText(message);
                    System.out.println("推送给用户【"+entry.getKey()+"】消息成功,消息为:" + message);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendMessage(List<String> userIds,String message){
        try {
            if(userIds == null || userIds.size() == 0){
                System.out.println("客户ID不能为空");
                return ;
            }
            for(Map.Entry<String, WebSocketDemo> entry : userMap.entrySet()){
                if(userIds.contains(entry.getKey())){
                    entry.getValue().getSession().getBasicRemote().sendText(message);
                    System.out.println("推送给用户【"+entry.getKey()+"】消息成功,消息为:" + message);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void sendAll(String message){
        try {
            if(!StringUtils.isNotBlank(userId)){
                System.out.println("客户ID不能为空");
                return ;
            }
            for(Map.Entry<String, WebSocketDemo> entry : userMap.entrySet()){
                entry.getValue().getSession().getBasicRemote().sendText(message);
                System.out.println("推送给用户【"+entry.getKey()+"】消息成功,消息为:" + message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取连接人数
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    //连接人数加一
    public static synchronized void addOnlineCount() {
        onlineCount+=1;
    }
    //连接人数减一
    public static synchronized void subOnlineCount() {
        if(onlineCount > 0){
            onlineCount-=1;
        }
    }

    public Session getSession() {
        return session;
    }

}

页面(HTML)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <title>保存更新</title>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
    <style>
        input,textarea{
            box-sizing: border-box;
            -webkit-box-sizing: border-box;
            -moz-box-sizing: border-box;
        }
    </style>
</head>
<body>
<input name="user" id="user" type="text" style="width: 100px"><button type="button" id="login">登录</button>
<form style="width: 300px;">
    <input name="tenantIds" placeholder="" style="width:100%;"  ><br>
    <button type="button" id="send" style="width:100%;" >提交</button><br>
    <div id="result" placeholder="结果提示" style="width:100%;height: 500px;border: gray solid 1px" ></div>
</form>
</body>
<script>
   var webSocket = null;
   $(document).ready(function () {
       //模拟不同用户,实际开发中从session或redis里取
       //判断当前浏览器是否支持WebSocket
       $("#login").click(function () {
           var user = $("#user").val();
           if("WebSocket" in window) {
               webSocket = new WebSocket("ws://localhost:8080/ws/push/" + user);
               displayMsg('用户【' + user + '】尝试连接')

               //连接发生错误的回调方法
               webSocket.onerror = function(){
                   displayMsg("服务器连接【异常】");
               };


               //连接成功建立的回调方法
               webSocket.onopen = function(event){
                   displayMsg('用户【'+user+'】服务器连接【成功】')
                   setInterval(function () {
                       webSocket.send("ping")
                   },10000)
               }


               //接收到消息的回调方法
               webSocket.onmessage = function(event){
                   displayMsg(event.data);
               }


               //连接关闭的回调方法
               webSocket.onclose = function(){
                   displayMsg("连接关闭");
               }


               //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
               window.onbeforeunload = function(){
                   websocket.close();
               }
           }else{
               displayMsg('当前浏览器可能不支持WebSocket')
           }
       })

       //关闭连接
       function closeWebSocket(){
           websocket.close();
       }

       $("#send").click(function () {
           var message = $("input[name=tenantIds]").val();
           if (message == "") {
               displayMsg("访问消息不能为空")
           } else {
               webSocket.send(message);
               displayMsg("已发送:" + message)
           }
       })

       //将消息显示在网页上
       function displayMsg(innerHTML){
           document.getElementById('result').innerHTML += innerHTML + '<br/>';
       }
   })
</script>
</html>

实现实时推送(模仿聊天)

分别用:甲、乙、丙三个用户模拟登陆,丙统计登录人员
甲登录:

乙登录:
丙登录:

页面效果甲发消息

其他用户发消息和甲一样,都会推送,如乙回复消息:

关闭一个用户(关闭浏览器或退出)

会触发退出事件,关闭连接,修改在线人数

导包

在网上看很多都说需要引入整合包,(但是我这没引用也是正常的,也可能是其他地方引用了)

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

注意:WebSocket类中的onOpen,onClose等 的方法参数不能乱写,否则可能会报异常(部署异常,没有注解之类的)

扫码关注


搜索公众号:【爪哇日记】关注最新文章

SpringBoot WebSocket可以实现消息推送聊天室功能。通过使用Spring框架提供的WebSocket技术,可以轻松实现这些功能。具体的实现步骤可以参考Spring官方的教程,其中详细介绍了如何使用Spring实现WebSocket,包括建立连接、发送消息和接收消息等操作。 WebSocket是一种在客户端和服务器之间建立持久连接的协议,它允许服务器主动推送消息给客户端,而不需要客户端发送请求。这种实时推送的机制非常适合用于聊天消息推送功能。通过SpringBoot WebSocket,可以在服务器端处理聊天消息,然后将消息即时推送给客户端,实现实时聊天的功能。 在实现SpringBoot WebSocket聊天消息推送的过程中,可以通过建立连接、发送消息和接收消息等操作来完成消息的传递。建立连接时,客户端会向服务器发起WebSocket握手请求,服务器接收请求后进行握手处理,建立连接。建立连接后,客户端和服务器之间可以互相发送和接收消息实现聊天功能。服务器可以根据业务逻辑处理接收到的消息,并将消息推送给其他客户端。客户端接收到消息后可以进行展示或处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot+WebSocket实现消息推送及简单的聊天功能](https://download.youkuaiyun.com/download/typ1805/10730574)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [springBoot集成websocket实现消息实时推送提醒](https://blog.youkuaiyun.com/weixin_35815479/article/details/128027542)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Springboot整合Websocket(推送消息通知)](https://blog.youkuaiyun.com/qq_34709784/article/details/126391781)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值