SpringBoot整合 websocket 实现群聊,点对点聊天

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

1.websocket

websocket最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。浏览器和服务器只需要要做一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时向服务器发送数据。

第一、WebSocket是HTML5中的协议,支持持久连接;而Http协议不支持持久连接。

第二、首先,Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说

HTTP的生命周期通过 Request 来界定,也就是一个 Request 一个 Response ,那么在 HTTP1.0 中,这次HTTP请求就结束了。

在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是被动的,不能主动发起。

第三、传统的http请求,其并发能力都是依赖同时发起多个TCP连接访问服务器实现的(因此并发数受限于浏览器允许的并发连接数),而websocket则允许我们在一条ws连接上同时并发多个请求,即在A请求发出后A响应还未到达,就可以继续发出B请求。由于TCP的慢启动特性(新连接速度上来是需要时间的),以及连接本身的握手损耗,都使得websocket协议的这一特性有很大的效率提升。

第四、http协议的头部太大,且每个请求携带的几百上千字节的头部大部分是重复的,很多时候可能响应都远没有请求中的header空间大。如此多无效的内容传递是因为无法利用上一条请求内容,websocket则因为复用长连接而没有这一问题。

第五、当需要实现客户端刷新消息时,传统方案往往通过定时ajax请求实现,实际上对多数用户多数时间下这些请求都是无意义了,并且非常占用资源,websocket资源占用就小很多。

2.在springboot程序当中使用websocket,接下来这套程序能够实现的功能有:

websocket连接:

springboot聊天功能,架构,websocket,java,网络协议

 文章来源地址https://www.toymoban.com/news/detail-718811.html

上线通知:

springboot聊天功能,架构,websocket,java,网络协议

下线通知:

springboot聊天功能,架构,websocket,java,网络协议

在线人数统计:

springboot聊天功能,架构,websocket,java,网络协议

对所有人聊天:

springboot聊天功能,架构,websocket,java,网络协议

一对一聊天:

springboot聊天功能,架构,websocket,java,网络协议

第一步:导入websocket的依赖

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

第二步:websocket的配置我

/**
 * websocket的配置
 */
@Configuration
public class WebSocketStompConfig{
    @Bean
    public ServerEndpointExporter serverEndpointExporter()
    {
        return new ServerEndpointExporter();
    }
}

第三步:建立ServerEndpoint的java类,能够接受客户端发送过来的信息和发送给客户端信息。

@Component
@ServerEndpoint("/websocket/{username}")
public class WebSocket {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 在线人数
     */
    public static int onlineNumber = 0;
    /**
     * 以用户的姓名为key,WebSocket为对象保存起来
     */
    private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
    /**
     * 会话
     */
    private Session session;
    /**
     * 用户名称
     */
    private String username;
    /**
     * 建立连接
     *
     * @param session
     */
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session)
    {
        onlineNumber++;
        logger.info("现在来连接的客户id:"+session.getId()+"用户名:"+username);
        this.username = username;
        this.session = session;
        logger.info("有新连接加入! 当前在线人数" + onlineNumber);
        try {
            //messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
            //先给所有人发送通知,说我上线了
            Map<String,Object> map1 = Maps.newHashMap();
            map1.put("messageType",1);
            map1.put("username",username);
            sendMessageAll(JSON.toJSONString(map1),username);
 
            //把自己的信息加入到map当中去
            clients.put(username, this);
            //给自己发一条消息:告诉自己现在都有谁在线
            Map<String,Object> map2 = Maps.newHashMap();
            map2.put("messageType",3);
            //移除掉自己
            Set<String> set = clients.keySet();
            map2.put("onlineUsers",set);
            sendMessageTo(JSON.toJSONString(map2),username);
        }
        catch (IOException e){
            logger.info(username+"上线的时候通知所有人发生了错误");
        }
 
 
 
    }
 
    @OnError
    public void onError(Session session, Throwable error) {
        logger.info("服务端发生了错误"+error.getMessage());
        //error.printStackTrace();
    }
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose()
    {
        onlineNumber--;
        //webSockets.remove(this);
        clients.remove(username);
        try {
            //messageType 1代表上线 2代表下线 3代表在线名单  4代表普通消息
            Map<String,Object> map1 = Maps.newHashMap();
            map1.put("messageType",2);
            map1.put("onlineUsers",clients.keySet());
            map1.put("username",username);
            sendMessageAll(JSON.toJSONString(map1),username);
        }
        catch (IOException e){
            logger.info(username+"下线的时候通知所有人发生了错误");
        }
        logger.info("有连接关闭! 当前在线人数" + onlineNumber);
    }
 
    /**
     * 收到客户端的消息
     *
     * @param message 消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String message, Session session)
    {
        try {
            logger.info("来自客户端消息:" + message+"客户端的id是:"+session.getId());
            JSONObject jsonObject = JSON.parseObject(message);
            String textMessage = jsonObject.getString("message");
            String fromusername = jsonObject.getString("username");
            String tousername = jsonObject.getString("to");
            //如果不是发给所有,那么就发给某一个人
            //messageType 1代表上线 2代表下线 3代表在线名单  4代表普通消息
            Map<String,Object> map1 = Maps.newHashMap();
            map1.put("messageType",4);
            map1.put("textMessage",textMessage);
            map1.put("fromusername",fromusername);
            if(tousername.equals("All")){
                map1.put("tousername","所有人");
                sendMessageAll(JSON.toJSONString(map1),fromusername);
            }
            else{
                map1.put("tousername",tousername);
                sendMessageTo(JSON.toJSONString(map1),tousername);
            }
        }
        catch (Exception e){
            logger.info("发生了错误了");
        }
 
    }
 
 
    public void sendMessageTo(String message, String ToUserName) throws IOException {
        for (WebSocket item : clients.values()) {
            if (item.username.equals(ToUserName) ) {
                item.session.getAsyncRemote().sendText(message);
                break;
            }
        }
    }
 
    public void sendMessageAll(String message,String FromUserName) throws IOException {
        for (WebSocket item : clients.values()) {
                item.session.getAsyncRemote().sendText(message);
        }
    }
 
    public static synchronized int getOnlineCount() {
        return onlineNumber;
    }
 
}

第四步:编写简易的前端页面

<!DOCTYPE html>
<html>
<head>
    <title>websocket</title>
    <script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.min.js"></script>
    <script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
    <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
</head>
 
<body>
    <div style="margin: auto;text-align: center">
        <h1>Welcome to websocket</h1>
    </div>
    <br/>
    <div style="margin: auto;text-align: center">
        <select id="onLineUser">
            <option>--所有--</option>
        </select>
        <input id="text" type="text" />
        <button οnclick="send()">发送消息</button>
    </div>
    <br>
    <div style="margin-right: 10px;text-align: right">
        <button οnclick="closeWebSocket()">关闭连接</button>
    </div>
    <hr/>
    <div id="message" style="text-align: center;"></div>
    <input  type="text" th:value="${username}" id="username" style="display: none" />
</body>
 
 
<script type="text/javascript">
    var webSocket;
    var commWebSocket;
    if ("WebSocket" in window)
    {
        webSocket = new WebSocket("ws://localhost:9030/websocket/"+document.getElementById('username').value);
 
        //连通之后的回调事件
        webSocket.onopen = function()
        {
            //webSocket.send( document.getElementById('username').value+"已经上线了");
            console.log("已经连通了websocket");
            setMessageInnerHTML("已经连通了websocket");
        };
 
        //接收后台服务端的消息
        webSocket.onmessage = function (evt)
        {
            var received_msg = evt.data;
            console.log("数据已接收:" +received_msg);
            var obj = JSON.parse(received_msg);
            console.log("可以解析成json:"+obj.messageType);
            //1代表上线 2代表下线 3代表在线名单 4代表普通消息
            if(obj.messageType==1){
                //把名称放入到selection当中供选择
                var onlineName = obj.username;
                var option = "<option>"+onlineName+"</option>";
                $("#onLineUser").append(option);
                setMessageInnerHTML(onlineName+"上线了");
            }
            else if(obj.messageType==2){
                $("#onLineUser").empty();
                var onlineName = obj.onlineUsers;
                var offlineName = obj.username;
                var option = "<option>"+"--所有--"+"</option>";
                for(var i=0;i<onlineName.length;i++){
                    if(!(onlineName[i]==document.getElementById('username').value)){
                        option+="<option>"+onlineName[i]+"</option>"
                    }
                }
                $("#onLineUser").append(option);
 
                setMessageInnerHTML(offlineName+"下线了");
            }
            else if(obj.messageType==3){
                var onlineName = obj.onlineUsers;
                var option = null;
                for(var i=0;i<onlineName.length;i++){
                    if(!(onlineName[i]==document.getElementById('username').value)){
                        option+="<option>"+onlineName[i]+"</option>"
                    }
                }
                $("#onLineUser").append(option);
                console.log("获取了在线的名单"+onlineName.toString());
            }
            else{
                setMessageInnerHTML(obj.fromusername+"对"+obj.tousername+"说:"+obj.textMessage);
            }
        };
 
        //连接关闭的回调事件
        webSocket.onclose = function()
        {
            console.log("连接已关闭...");
            setMessageInnerHTML("连接已经关闭....");
        };
    }
    else{
        // 浏览器不支持 WebSocket
        alert("您的浏览器不支持 WebSocket!");
    }
    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }
 
    function closeWebSocket() {
        //直接关闭websocket的连接
        webSocket.close();
    }
 
    function send() {
        var selectText = $("#onLineUser").find("option:selected").text();
        if(selectText=="--所有--"){
            selectText = "All";
        }
        else{
            setMessageInnerHTML(document.getElementById('username').value+"对"+selectText+"说:"+ $("#text").val());
        }
        var message = {
            "message":document.getElementById('text').value,
            "username":document.getElementById('username').value,
            "to":selectText
        };
        webSocket.send(JSON.stringify(message));
        $("#text").val("");
 
    }
</script>
 
</html>

第五步:跳转到websocket页面上去

    @RequestMapping("/websocket/{name}")
    public String webSocket(@PathVariable String name,Model model){
        try{
            logger.info("跳转到websocket的页面上");
            model.addAttribute("username",name);
            return "websocket";
        }
        catch (Exception e){
            logger.info("跳转到websocket的页面上发生异常,异常信息是:"+e.getMessage());
            return "error";
        }
    }

以上能够实现的功能有上线通知,下线通知,一对一聊天,对所有人聊等功能,有问题欢迎留言,谢谢。

 

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

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

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

相关文章

  • 【WebSocket】SpringBoot整合WebSocket实现聊天室(一)

    目录 一、准备 1、引入依赖 2、创建配置类 二、相关注解 首先我们需要在项目中引入依赖,有两种方式。第一种我们可以在创建Spring Boot项目时搜索WebSocket然后勾选依赖 第二种是我们可以直接在项目的pom.xml文件中插入以下依赖 我们需要进行如下配置 ServerEndpointExporter 是一个

    2024年02月13日
    浏览(45)
  • SpringBoot+Vue 整合websocket实现简单聊天窗口

    1 输入临时名字充当账号使用 2 进入聊天窗口 3 发送消息 (复制一个页面,输入其他名字,方便展示效果) 4 其他窗口效果 pom依赖 WebSocketConfig.java WebSocketServer.java MessageVo.java App.vue

    2024年02月09日
    浏览(43)
  • springboot整合tio-websocket方案实现简易聊天

    一、导包(导入TIO的两个依赖,其他必要依赖不赘述) 二、yml配置 三、配置参数 四、实现一些监听类 1.ServerAioListener监听 2.IpStatListener监听(这个可选) 3.WsServerAioListener监听 4.IWsMsgHandler拦截(里面逻辑根据具体业务,但是必须实现这个,不然启动报错) 五、一些消息体(根据

    2024年02月14日
    浏览(36)
  • SpringBoot 整合 Websocket 通信demo (附浏览器聊天窗口)

    【男性深夜解压神器】 https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.1d293d0dZgIXMJft=tid=742087626933

    2024年02月08日
    浏览(32)
  • C#实现udp点对点通信的完整示例

    udp和tcp都是传输协议,最大的不同是,tcp通信前需要建立连接,是更可靠的通信协议,而udp是一个无连接的传输协议,可直接发送数据。两种协议不分优劣,各有各的应用场景,实际应用往往会同时使用两种协议。 C#代码实现udp通信的步骤比较简单。 假设:A要向B发送消息。

    2024年02月16日
    浏览(41)
  • 虚拟专用网络(VPN):远程访问与点对点连接及其在Linux中的IPSec实现与日志管理

    **虚拟专用网络(VPN)**是一种强大的网络安全技术,它利用加密隧道技术,在不安全的公共网络上建立安全的数据传输通道。VPN不仅保护了数据的隐私和完整性,还使得用户无论身处何地都能如同在本地一样访问受保护的网络资源。 远程VPN 在Linux环境中,远程VPN通常通过安装客

    2024年01月18日
    浏览(49)
  • 基于Springboot整合Socket仿微信实现群聊、私聊功能。实现客户端client,服务端server心跳维护、超时机制【一文通】

    博主介绍: ✌java资深开发工程师、Java领域优质创作者,博客之星、专注于Java技术领域和学生毕业项目实战,面试讲解跟进,高校老师/讲师/同行交流合作✌ 胡广愿景: \\\"比特星球\\\",致力于帮助底层人员找到工作, 让每个底层人员都能找到属于自己的星球。 拓展学习领域,获

    2024年02月19日
    浏览(51)
  • 组件分享之后端组件——基于Golang实现的全局的、版本化的、点对点的文件系统go-ipfs...

    近期正在探索前端、后端、系统端各类常用组件与工具,对其一些常见的组件进行再次整理一下,形成标准化组件专题,后续该专题将包含各类语言中的一些常用组件。欢迎大家进行持续关注。 组件: go-ipfs 开源协议:The go-ipfs project is dual-licensed under Apache 2.0 and MIT terms: Ap

    2024年02月01日
    浏览(42)
  • SpringBoot集成WebSocket实现在线聊天

    在项目过程中涉及到了在线聊天的业务,刚好有了解到WebSocket可以实现这一功能,因此便对其进行了一定的研究并做下笔记,在本文中主要借鉴了以下资源: WebSocket_百度百科 李士伟的小程序聊天工程 Springboot+Websocket中@Autowired注入service为null的解决方法 WebSocket是 HTML5规范 中

    2024年02月04日
    浏览(39)
  • SpringBoot集成WebSocket实现及时通讯聊天功能!!!

    注意:   至此,后端代码就集成完了,集成完之后,记得重启你的Springboot项目 前端Vue 1:新建Vue 页面  路由: 代码:路由根据你项目的实际情况写 在用户登录的时候,需要将你的用户名存储到本地Session 中  效果图:  用户甲:   用户乙:   注:网上学习来源 SpringBoot集

    2024年02月01日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包