WebScoket聊天室Springboot版

web网页端使用webSocket实现语音通话功能(SpringBoot+VUE) 借助webSocket全双工通信的方式来实现web客户端之间的语音通话,解决网上能找到的一个代码使用之后只能听到“嘀嘀嘀”杂音的问题 阅读详情

本文是基于注释的案例,对于发送语音采用了类似文件上传下载一样的方式实现,不过播放会有一点儿延迟,正在改进。

1、首先导入webScoket相关的jar

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

2、开启WebScoket支持

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * 开启WebSocket支持
 */
@Configuration
public class WebSocketConfig {
/**
*外置tomcat不需要配置此bean 
*/
   @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

3、定义一个websocket服务器端

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint(value = "/{room}/{Id}")
@Component
public class MyWebSocket {

    /**
     * 自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的
     */
    private static AtomicInteger room1OnlineCount = new AtomicInteger(0);
    private static AtomicInteger room2OnlineCount = new AtomicInteger(0);
    private static AtomicInteger room3OnlineCount = new AtomicInteger(0);
    /**
     * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     */
  /*  private static CopyOnWriteArraySet<MyWebSocket> room1WebSocketSet = new CopyOnWriteArraySet<>();
    private static CopyOnWriteArraySet<MyWebSocket> room2WebSocketSet = new CopyOnWriteArraySet<>();
    private static CopyOnWriteArraySet<MyWebSocket> room3WebSocketSet = new CopyOnWriteArraySet<>();
*/
    /**
     * 所有的MyWebSocket对象放在一个map中,方便私聊直接发送
     */
    private static ConcurrentHashMap<String, MyWebSocket> roomMap = new ConcurrentHashMap<>(10000);
    /**
     * 每个聊天室一个map方便群发信息
     */
    private static ConcurrentHashMap<String, MyWebSocket> room1Map = new ConcurrentHashMap<>(10000);
    private static ConcurrentHashMap<String, MyWebSocket> room2Map = new ConcurrentHashMap<>(10000);
    private static ConcurrentHashMap<String, MyWebSocket> room3Map = new ConcurrentHashMap<>(10000);
    /**
     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    private Session session;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("Id") String Id, @PathParam("room") String room) {

            this.session = session;
            //在线人数++
            room1OnlineCount.incrementAndGet();
            roomMap.put(Id,this);
            System.out.println(this.session.getId());
            String substring = room.substring(room.length() - 1);
            if (Integer.parseInt(substring) == 1) {
                //session加入room1
               // room1WebSocketSet.add(this);
                room1Map.put(Id,this);
                //在线人数++
                room1OnlineCount.incrementAndGet();
            } else if (Integer.parseInt(substring) == 2) {
                //session加入room2
              //  room2WebSocketSet.add(this);
                room2Map.put(Id,this);
                //在线人数++
                room2OnlineCount.incrementAndGet();
            } else {
                //session加入room3
              //  room3WebSocketSet.add(this);
                room3Map.put(Id,this);
                //在线人数++
                room3OnlineCount.incrementAndGet();
            }
        }

        /**
         * 连接关闭调用的方法
         */
    @OnClose
    public void onClose( @PathParam("Id")String userId, @PathParam("room")String room) {
        //room1WebSocketSet.remove(this);
        room1OnlineCount.decrementAndGet();
        String substring = room.substring(room.length() - 1);
        if (Integer.parseInt(substring)==1){
          //  room1WebSocketSet.remove(this);
            room1Map.remove(userId);
            room1OnlineCount.decrementAndGet();
        }else if (Integer.parseInt(substring)==2){
          //  room2WebSocketSet.remove(this);
            room2OnlineCount.decrementAndGet();
            room2Map.remove(userId);
        }else{
        //    room3WebSocketSet.remove(this);
            room3OnlineCount.decrementAndGet();
            room3Map.remove(userId);
        }
        System.out.println("有一连接关闭!当前在线人数为" + room1OnlineCount);
    }

    /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息
         * */

    @OnMessage
    public void onMessage(String message,@PathParam("room")String room) {
        System.out.println(message);
        //客户端定时ping一下,如果不同就直接重新建立连接
        /*if (message.equals("ping")){
            try {
                this.session.getBasicRemote().sendText("pong");
            } catch (IOException e) {
                System.out.println("IO 异常");
                e.printStackTrace();
            }
        }*/
        String KEY_PRE = "All";
        JSONObject jsonObject = JSON.parseObject(message);
        String to = jsonObject.getString("to");
        String substring = room.substring(room.length() - 1);
        if(KEY_PRE.equals(to)){
            sendMessageToAll(message,substring);
        }else{
            sendMessage(message, to);
        }

    }

    /**
     * 发生错误时调用
     * @param error
     */
     @OnError
     public synchronized void onError(Throwable error) {
         System.out.println("发生错误");
         error.printStackTrace();
     }

    /**
     * 私聊
     * @param message
     */
     public void sendMessage(String message,String Id){
         //判断链接是否正常
             try {
                 //根据ID查到接收方的session发送信息
                 roomMap.get(Id).session.getBasicRemote().sendText(message);
             } catch (IOException e) {
                 e.printStackTrace();
             }
    }

    /**
     * 群发
     * @param message
     * @param room
     */
    public void sendMessageToAll(String message,String room){
       // if(this.session.isOpen()){
        System.out.println(message);
            try {
                if(room.equals("1")){
                    for(String key : room1Map.keySet()){
                        room1Map.get(key).session.getBasicRemote().sendText(message);
                    }
                }
                if(room.equals("2")){
                    for(String key : room2Map.keySet()){
                        room2Map.get(key).session.getBasicRemote().sendText(message);
                    }
                }
                if(room.equals("3")){
                    for(String key : room3Map.keySet()){
                        room3Map.get(key).session.getBasicRemote().sendText(message);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    //}
}

4、发送语音的controller

/**
 * 发送语音和上传文件
 */
@RestController
@RequestMapping("/api")
public class FileWebScoket {

    /**
     * 录音图片上传
     * @param request
     * @param file
     * @param room
     */
    @RequestMapping(path = { "websocket-file" }, method = { RequestMethod.POST })
    public void fileUpload(HttpServletRequest request, @RequestParam("file") MultipartFile file,String room,String type,String userName,String userImg,String id,String to) {
        // 判断文件是否为空
        String str ="/public/"+System.currentTimeMillis()+file.getOriginalFilename();
        String filePath=request.getServletContext().getRealPath("/")+"/WEB-INF"+str;
        if (!file.isEmpty()) {
            try {
                // 文件保存路径
                file.transferTo(new File(filePath));
                MyWebSocket webSocket=new MyWebSocket();
                webSocket.sendMessageToAll("{\"type\":" +type+
                        ",\"userName\":\"" +userName+
                        "\",\"userImg\":\"" +userImg+
                        "\",\"audio\":\""+
                        str+"\",\"id\":" +id+
                        ",\"content\":\"1111\",\"to\":\"" +to+
                        "\"}", room);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

   /* @RequestMapping(path = { "websocket-file-1" }, method = { RequestMethod.POST })
    public void importAudio(HttpServletRequest request,@RequestParam("file") String file) {
        file = file.replaceAll("data:audio/mp3;base64,","");
        byte[] audioByte=Base64.decodeBase64(file);
        String fileName= KeyUtil.genUniqueKey()+".mp3";
        String filePath=request.getServletContext().getRealPath("/")+"/WEB-INF/public/";
        try {
            FileUtil.uploadFile(audioByte, filePath, fileName);
            MyWebSocket webSocket=new MyWebSocket();
            webSocket.sendMessageToAll("", "1");
        }catch (Exception e){
            e.printStackTrace();
        }
    }*/
}

到此已经基本实现了基本功能。

接下来试试使用buffer直接推送语音,这样可能发送语音不会有延迟的现象,语音直接保存在客户端,直接点击播放。

Java使用WebSocket完成聊天室 本文作者:禹明明,叩丁狼高级讲师。原创文章,转载请注明出处。  WebSocket是基于TCP的一种新的网络协议,最大的特点就是实现了浏览器与服务器全双工(full-duplex)通信,2011年WebSocket协议被接受为国际标准 HTML5开始提供WebSocket协议的支持。 什么叫全双工通讯? 其实就是通信的双方都可以主动发送消息,又可以接受消息.WebSocket协议之前,全双工通... 阅读详情

相关推荐

Spring Boot整合websocket实现群聊,点对点聊天,图片发送,音频发送

Spring Boot整合websocket实现群聊,点对点聊天,图片发送,音频发送

WebSocket+Vue+SpringBoot实现语音通话

前端点击开始对话按钮后,将监听麦克风,获取到当前的音频,将其装化为二进制数据,通过websocket发送到webscoket服务端,服务端在接收后,将消息写入给指定客户端,客户端拿到发送过来的二进制音频后再转化播放。

weixin_48974246的博客 1万+

Springboot基于websocket实现简单在线聊天功能

主要介绍了Springboot基于websocket实现简单在线聊天功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

Spring笔记(9):SpringBoot WebSocket 实时语音聊天

主要参考了这两篇博客 https://blog.youkuaiyun.com/zhang45362613/article/details/112538607 这一篇的采集方案,采集到语音数据后上传服务器 https://blog.youkuaiyun.com/qq422243639/article/details/79238983 这一篇的自动播放方案,websocket接收到数据后,立即播放 其实这一篇涵盖了采集的方案,但是代码有许多过时的语句,也就没有采用 前端代码: 其中有很多需要调用的js文件,可以直接去git这个项目,里

Cake_C的博客 4997

从USB相机标定到Aruco码精准定位:基于aruco-ros的机器人视觉实践

本文详细介绍了基于aruco-ros的机器人视觉实践,从USB相机标定到Aruco码精准定位的全流程。通过实战案例和优化技巧,展示了Aruco码在机器人导航中的高精度位姿识别能力,帮助开发者快速实现毫米级视觉定位系统。

weixin_27310417的博客 487

别再只飞不记了!用CsvView分析你的大疆飞行日志,优化航拍与排查炸机原因

本文详细介绍了如何利用CsvView工具分析大疆无人机的飞行日志,帮助用户优化航拍效率和飞行安全。通过解读飞行日志中的关键数据,如电池性能、飞行轨迹等,用户可以及时发现潜在问题并改进飞行习惯。文章还提供了事故排查方法和进阶分析技巧,适合无人机爱好者和专业飞手。

weixin_42535461的博客 547

SpringBoot集成WebSocket实现在线聊天

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

陈宝子的博客 7926

【水文】calico-node 启动失败 Init:CrashLoopBackOff

Defaulted container "calico-node" out of: calico-node, upgrade-ipam (init), install-cni (init), mount-bpffs (init) Error from server (BadRequest): container "calico-node" in pod "calico-node-4j7td" is waiting to start: PodInitializing

大健的日常的博客 1万+

【十五】springboot整合WebSocket实现聊天室

springboot整合WebSocket实现聊天室

weixin_56995925的博客 2万+

S32K3双核实战:手把手教你用EB配置CAN与CANFD(附中断/轮询代码对比)

本文详细解析了NXP S32K3双核处理器在CAN/CANFD通信开发中的实战应用。通过Elektrobit配置工具链,从双核通信架构设计到EB tresos Studio配置全流程,再到中断与轮询模式的代码实现对比,全面指导开发者优化S32K3 FlexCAN模块性能,提升汽车电子系统的通信效率与可靠性。

weixin_30955617的博客 440

Vibe Coding 工具实战案例全解:Cursor、Claude Code、Codex 真实项目 30 分钟到 4 小时快速构建指南(2026 年最新)

2026年VibeCoding工具实战案例精选:1)使用Cursor在30分钟内构建现代TodoList应用(Next.js+TS+Tailwind);2)通过ClaudeCode纯终端2小时开发3D飞行射击游戏(Three.js+R3F);3)利用OpenAICodex多Agent并行4小时完成SaaS全栈开发(Next.js+Supabase+Stripe)。案例均来自真实项目,覆盖从入门到生产级开发,重点展示:自然语言Prompt技巧、迭代反馈方法、工具特性对比(Cursor可视化最佳/Claude推

hy行者勇哥的博客 3167

Springboot整合WebScoket实现在线聊天室

SpringBoot+WebScoket在线聊天室 提示:本次作者使用的环境是Windows10+jdk1.8+maven3.6.1 + idea2020.03 注:本版本只是一个简易版本的聊天室,更多功能可以自己自己去扩充,新手上路,老鸟勿喷,欢迎所有热爱java的朋友加作者wx文章目录SpringBoot+WebScoket在线聊天室第一步:创建SpringBoot项目导入maven依赖第二步:配置文件第二步:创建index.html页面(templates下)第三步:创建Conteoller页面跳转第

xiaowang199303的博客 568

汽车安全新防线|基于AI的入侵检测系统开发(全网独家复现),CNN-BiLSTM融合改进篇 强化CAN总线数据感知、助力多类型入侵检测、实时响应预警、车载场景有效落地

基于AI的入侵检测系统是汽车网络安全领域的重要技术突破,能够有效应对日益复杂的网络攻击威胁。随着AI技术的不断发展和普及,AI入侵检测系统将在汽车安全领域发挥越来越重要的作用。对于汽车制造商和供应商来说,实施AI入侵检测系统不仅是保障车辆安全的需要,也是提升市场竞争力的重要手段。未来,AI入侵检测系统将成为智能汽车的标准配置,为用户提供更加安全、可靠的驾驶体验。

getusushu的博客 85

基于webscoket的简易聊天室项目+前后端代码实现

基于webscoket的聊天室项目,实现了注册(邮箱验证码注册)登录与聊天功能,前端使用vue,聊天室支持markdown语法实现了代码高亮。支持发送图片和文件,发送的图片和文件保存在阿里云oss

zxwyhzy的博客 4581

第9.3章 从CMake基础到自动驾驶实战:构建跨平台C/C++项目的全能指南

《CMake构建实战:项目开发卷》精要指南 本文系统梳理了许宏旭《CMake构建实战》核心内容,涵盖C++构建全流程: 基础构建:详解MSVC/GCC编译器使用、Makefile编写及静态/动态库构建方法 CMake核心:解析语法结构、变量控制、文件操作等关键命令,阐述项目全生命周期管理 实战应用:通过快速排序、手写数字识别项目演示现代CMake实践,特别针对自动驾驶领域给出多传感器融合、SLAM等场景的CMake配置方案 特色价值:本书填补了官方文档实例不足的空白,提供300+代码示例,是掌握工业级C++

行知SLAM 1343

ArcGIS实验教程——实验十九:网络分析(最短路径实现)

一、实验描述 网络分析模块用于实现基于网络数据集的网络分析功能,包括路径分析、服务区分析、最近设施点分析、OD成本矩阵分析、多路径配送分析、位置分配分析和高级网络的管理与创建等。 网络数据集不同于几何网络,是一种高级的连接模型,能够展示复杂的细节,拥有丰富的网络属性模型,可以模拟网络阻力、网络限制以及网络层次等。 本实验重点演示网络分析中最短路径的实现过程。 二、实验内容 1、网络数据集...

智慧空间实验室 5681

springboot+websocket实现在线多功能聊天室

基于WebSocket的多功能在线聊天室 系统简述 本系统是一款基于WebSocket 的多功能在线聊天网站,项目架构基于Springboot+Layui+Mybatis-Plus+Websocket实现,项目的主要功能分为用户登录、邮箱注册用户、好友聊天、好友添加、语音发送以及表情管理和图片上传等功能。 系统平台 开发环境:Windows10 开发语言:Java 开发工具:IDEA Navicat15 数据库:Mysql8.0 系统结构图 项目结构图 执行结果 项目源代码 项目源代码(包含

whut小宝的博客 1万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

基于 WebSocket 技术实现聊天室功能

/ 自定义保存的文件名。//用来存储每一个客户端对象对应的ChatEndpoint对泉。SpringBoot项目基于 WebSocket 技术实现聊天室功能。//将message转挽成Message对象。//将当前在线用户的ip地址推送给所有的客户端。//要将该消息推送给所有的客户端。// 接收到的是图片消息。// 保存为图片文件。//2,调用方法进行系统消息的推达。//将图片文件转换成 Base64 字符串。//将当前对象存储到容器中。// 保存字节数组为图片文件的方法。//从容器中删除指定的用户。

Mr_he_king的博客 145

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

springboot+websocket聊天室(多人聊天,单人聊天)

springboot+websocket聊天室(多人聊天,单人聊天)源码下载地址 https://download.youkuaiyun.com/download/qq_37174383/10635130     WebSocket 是什么? WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全...

qq_37174383的博客 1780

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

聊天室功能实现

结构图(使用mybatisplus) webSocket配置类:WebSocketConfig.java package com.example.springboot_websocket.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ster..

m0_57891856的博客 518

SpringbootWebSocketRedis实现聊天室:实时通信的解决方案

SpringbootWebSocketRedis实现聊天室:实时通信的解决方案 【下载地址】SpringbootWebSocketRedis实现聊天室 这是一个基于Spring Boot、WebSocket和Redis技术栈实现的聊天室应用,支持私聊、群聊及图片发送功能。通过WebSocket实现实时通信,确保消息的即时...

gitblog_06738的博客 1132

SpringBoot + Websocket + Vue 构建聊天室

关于 WebSocket: 1、WebSocket 是 html5 提供的通讯协议 2、特点是建立在单个 tcp 连接上的全双工协议 3、浏览器向服务器发起 WebSocket 连接请求,当成功获取到连接后,就可以实现浏览器和服务器之间的数据传输

后端为主,前端为辅。 940

Websocket实现简易聊天室功能

WebSocket WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。 WebSocke

我的鱼要死了的博客 646

springboot进阶学习(五)springboot集成websocket

springboot集成websocket websocket能干什么 主动从服务端向客户端传递消息,这个可以实现我们定时获取后台信息的需求。前台页面不需要定期刷新,后台可以定时或者有更新的时候向前台传递信息。 可以实现类似聊天室的需求。 基本实例 引入所需的jar包 <!-- websocket --> <dependency> <groupId>org.springframework.boot</groupId> <artifactI

牛魔王的专栏 405

SpringBoot 第二十三篇:打造属于你的聊天室(WebSocket)

本文详细介绍了基于Spring Boot和WebSocket的实时聊天室实现方案。首先对比了WebSocket与HTTP协议的特性差异,突出了WebSocket在实时通信中的优势。然后逐步讲解了后端实现:通过Spring Boot集成WebSocket,配置STOMP协议端点,实现消息控制器处理公共聊天、私聊和用户状态管理。前端使用SockJS和STOMP.js建立连接,实现消息收发和用户界面交互。文章还介绍了高级功能扩展,包括消息持久化、已读状态和安全配置。最终实现了一个功能完善的实时聊天系统,支持用户上

油墨香^-^的博客 843

java websocket 微服务_微服务-springboot+websocket在线聊天室

一.引入依赖org.springframework.bootspring-boot-starter-websocket二.注入ServerEndpointExporter编写一个WebSocketConfig配置类,注入对象ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpointimportorg.spr...

weixin_39995351的博客 638
上一篇: Linux配置两个Tomcat
下一篇: JavaEE知识点
sike_java
博客等级 码龄9年 16粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值