国庆假期,整整七天,我使用SpringBoot终于做出了即时通信!!!😤

简介: 7天时间,踩了很多很多坑,终于完成了SpringBoot WebSocket即时通讯的功能,个人觉得蛮有学习意义的,来看看吧!哦对了,求个赞,哥哥们,国庆假期就贡献在这里啦~

前言:(本文用于辅助Flutter WebSocket的理解) 在这个假期,我完成了一个小Demo,Flutter 与 Springboot 进行websocket的通讯,为啥想要去做这个Demo呢,主要是在各大平台以及google搜索后发现,没有一个详细的例子来教大家进行一对一、一对多的通讯,大多数都是教你怎么连接,却没有教你怎么去进行下一步的功能实现,于是我利用了五天的假期,踩了无数的坑,终于是完成了它,所以,点个赞吧,不容易啊,兄弟们😭

github仓库还没有创建(可以看一下文末通知),前端界面也写好了,如果想要移动端的效果的话需要使用Flutter😎

Flutter移动端分析:Flutter WebSocket 即时通讯

先上效果图(我自己搜索这样功能性的问题时,没有效果图基本上都是不想看的):

屏幕截图 2021-10-08 122313.jpg

这个效果图为Flutter:

tt0.top-039531.gif

即时通讯最重要的功能是完成了(发送文字信息)

阅读本文的注意点:

本文参考https://www.zhihu.com/column/p/32282342,在其基础上进行二次开发

1.需要一点WebSocket的原理知识

2.springboot使用WebSocket的方法,本章就是最普通的原生方法

WebSocket的原理知识在Flutter WebSocket这篇文章中已经讲了,这里就不再重复了

正文:

1.Springboot使用WebSocket的方法

https://juejin.cn/post/6844903976727494669 掘金里已经有大神详细的讲解了

这里推荐spring封装或者STOMP两种方式

讲几个注意的点(详细的步骤掘金里的大神都已经写过啦~):

  • pom.xml 配置websocket
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

如果需要用户存储功能可以使用Spring Security,用户授权非常方便

  • STOMP这个协议是非常优秀的,是一种简单的基于文本的消息传递协议

如果想学习的,我推荐这篇大佬的文章:https://juejin.cn/post/6844903856413868040

2.Springboot实现点对点通信

现在步入正文

  • 配置pom.xml

    在默认的环境下,加上一个websocket即可,这里使用的是JDK8

<properties>
    <java.version>1.8</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
​
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
  • 封装前端传入的信息,以及return的值:

    因为使用json进行消息的发送,所以需要先创建一个消息对象,包含了消息发送者,消息接受者,消息类型

    //数据类型
    public class SocketMsg {
        private int type;//聊天类型0:群聊,1:单聊.
        private String fromUser;//发送者.
        private String toUser;//接受者.
        private String msg;//消息
    ​
        ...省略了get 和 set方法,不想写的话可以尝试lombook
    }
  • WebSocketConfig处理

    这里就简单举了个例子,文章中其实没有怎么用到

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
​
@Configuration
public class WebSocketConfig {
    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        // ws 传输数据的时候,数据过大有时候会接收不到,所以在此处设置bufferSize
        container.setMaxTextMessageBufferSize(512000);
        container.setMaxBinaryMessageBufferSize(512000);
        container.setMaxSessionIdleTimeout(15 * 60000L);
        return container;
    }
}
  • 最重要的内容,逻辑处理部分MyWebSocket来啦!
  • 设置websocket连接点映射:

    @ServerEndpoint(value = "/websocket/{nickname}")
  • 我们需要一个变量来存储每个客户端对应的MyWebSocket对象.
private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();

一个变量用来记录sessionId和该session之间的绑定关系.

private static Map<String, Session> map = new HashMap<String, Session>();
  • 成功建立连接时
@OnOpen
public void onOpen(Session session, @PathParam("nickname") String nickname) {
    this.session = session;
    this.nickname = nickname;
    map.put(session.getId(), session);
    webSocketSet.add(this);//加入set中.
    this.session.getAsyncRemote().sendText(nickname + "上线了,(我的频道号是" + session.getId() + ")");
}
  • 收到客户端消息后调用
@OnMessage
public void onMessage(String message, Session session, @PathParam("nickname") String nickname) {
    //message 不是普通的string ,而是我们定义的SocketMsg json字符串.
    try {
        SocketMsg socketMsg = new ObjectMapper().readValue(message, SocketMsg.class);
        //一对一聊天
        if (socketMsg.getType() == 1) {
            //只需要找到发送者和接受者即可.
            socketMsg.setFromUser(session.getId());//发送者.
            //socketMsg.setToUser(toUser);//这个是由客户端进行设置.
            Session fromSession = map.get(socketMsg.getFromUser());
            Session toSession = map.get(socketMsg.getToUser());
            if (toSession != null) {
                //发送消息
                fromSession.getAsyncRemote().sendText(nickname + ":" + socketMsg.getMsg());
                toSession.getAsyncRemote().sendText(nickname + ":" + socketMsg.getMsg());
            } else {
                fromSession.getAsyncRemote().sendText("系统消息:对方不在线或者您输入的频道号有误");
            }
        } else {
            //群发给每个客户端
            broadcast(socketMsg, nickname);
        }

    } catch (JsonParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JsonMappingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
  • 发生错误时
public void onError(Session session, Throwable error) {
    System.out.println("发生错误");
    error.printStackTrace();
}
  • 如果选择群发时(每个在线的客户都可以收到信息)

    private void broadcast(SocketMsg socketMsg, String nickname) {
        for (MyWebSocket item : webSocketSet) {
            //发送消息.
            item.session.getAsyncRemote().sendText(nickname + ":" + socketMsg.getMsg());
        }
    }
  • 连接关闭

    @OnClose
    public void onClose(Session session) {
        webSocketSet.remove(this);//从set中移除.
        map.remove(session.getId());
    }

使用源码时注意,本章使用JDK8,websocket的版本可能略有不同,端口为9090,具体的使用方法可以参考Flutter WebSocket的文章最后~

通知:https://juejin.cn/pin/7034450183706378270

相关文章
|
JSON Dart 安全
国庆假期,整整七天,我使用Flutter终于做出了即时通信!!!😤
7天时间,踩了很多很多坑,终于完成了Flutter WebSocket即时通讯的功能,个人觉得蛮有学习意义的,来看看吧!哦对了,求个赞,哥哥们,国庆假期就贡献在这里啦~
|
Web App开发 人工智能 小程序
爆肝熬夜开发了一个SpringBoot活动管理系统,现在开源给你!毕设面试学习都不愁了!
基于springboot的小程序系统,前台是小程序,后台用springboot开发的,源码进行开源。系统和奈斯,前台面向的是用户,可以进行登录、注册、在线预约活动、公告查看、活动分类查看等
372 0
爆肝熬夜开发了一个SpringBoot活动管理系统,现在开源给你!毕设面试学习都不愁了!
|
7月前
|
测试技术 程序员 项目管理
甲方怒喷半小时:一次项目上线失败的深刻教训
小米分享了一次项目上线失败的经历,起因是运营提出一个看似简单的白名单功能。问题包括:没有需求原型导致理解偏差,新成员对项目不熟悉,测试流程不全面,以及人员变动大。解决方案涉及需求确认会、原型图设计、交接制度、团队培训和全流程测试等。这次失败提供了关于需求分析、项目管理及团队协作的教训。
61 2
|
7月前
|
安全 Java 数据库连接
首次面试经历(忘指导)当我在简历上写了苍穹外卖,瑞吉外卖时……
首次面试经历(忘指导)当我在简历上写了苍穹外卖,瑞吉外卖时……
1272 2
|
7月前
|
数据采集 NoSQL 搜索推荐
五一假期畅游指南:Python技术构建的热门景点分析系统解读
五一假期畅游指南:Python技术构建的热门景点分析系统解读
|
前端开发 Java 数据库
SpringBoot日记本系统全程直播01:先把框架搞起来撒~~
SpringBoot日记本系统全程直播01:先把框架搞起来撒~~
131 0
连夜整理七个开源项目:练手、毕设、接私活都不愁了
项目一:cloud-platform 学习重点: 服务鉴权中心 用户间鉴权 服务之间鉴权 springcloud组件大回顾
|
监控 前端开发 jenkins
新来个技术总监,给团队引入了这款开发神器,同事直呼哇塞
带团队时间久了,就能发现整个 Team 都渐渐疲了。前两年老板还专门买了个系统搞 OKR,现在也不大提了;Scrum 我们也搞了,用起来也就那样;项目管理工具试了好几个,禅道、Worktile、现在用 Coding,反正有一个能用的就行;微服务化改造从去年开始在吭哧吭哧搞,我们自己搞得觉得很厉害,但业务部门那边就觉得没啥差别,搞不懂你们研发部门每天在弄些什么,赶紧做我们提的需求要紧。
新来个技术总监,给团队引入了这款开发神器,同事直呼哇塞
|
机器学习/深度学习 人工智能 自然语言处理
【paddlehubOCR项目】网课手酸酸,眼花花,救星来啦!
大家好这里是三岁,今天给大家带来的是在AiStudio项目平台的一个精选项目,虽然很短,但是效果拔群,使用到了最近特别火的paddleOCR~~~
274 0
【paddlehubOCR项目】网课手酸酸,眼花花,救星来啦!
|
Java 关系型数据库 MySQL
假期第二天,给老板写一个基于SSM框架的在线考试系统
本文主要是基于JSP+SSM+MySQL的开发模式。该系统采用Spring框架和Mybatis框架,将该两项技术进行整合,完成系统的开发,系统采用B/S的体系结构和免费的MySQL作为数据库服务器可以降低成本,服务器方面则选择了Apache旗下开源的Tomcat 8.0版本。该系统主要实现了考生的考试功能和后台管理功能。
221 0
假期第二天,给老板写一个基于SSM框架的在线考试系统