springboot框架下利用websocket实现即时通讯(文章末尾有git项目打包文件,直接下载使用即可)

用websocket实现简单的在线聊天,先画个时序图,直观感受下流程

SystemController类

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;/*** @描述 WebSocket消息推送控制器* @创建人 poneco* @创建时间 2021/11/16*/
@RestController
public class SystemController {// 推送数据到websocket客户端 接口@GetMapping("/socket/push/{cid}")public Map pushMessage(@PathVariable("cid") String cid, String message) {Map<String, Object> result = new HashMap<>();try {HashSet<String> sids = new HashSet<>();sids.add(cid);WebSocketServer.sendMessage("服务端推送消息:" + message, sids);result.put("code", cid);result.put("msg", message);} catch (IOException e) {e.printStackTrace();}return result;}
}

WebSocket类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @描述 开启WebSocket支持的配置类* @创建人 poneco* @创建时间 2021/11/16*/
@Configuration
public class WebSocket {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}

WebSocketServer

import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
/*** @描述 WebSocket核心配置类* @创建人 poneco* @创建时间 2021/11/16*//*** @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端。*/
@Component
@Slf4j
@Service
@ServerEndpoint("/api/websocket/{userID}/{touserID}")
public class WebSocketServer {//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。private static AtomicInteger onlineCount = new AtomicInteger(0);//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();// private static ConcurrentHashMap<String, WebSocketServer> webSocketSet = new ConcurrentHashMap<>();//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;//接收sidprivate String userID = "";private String touserID="";/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("userID") String userID,@PathParam("touserID") String touserID) {log.info(String.valueOf(session.getRequestURI()));this.session = session;this.userID = userID;this.touserID = touserID;log.info("接受者"+touserID);webSocketSet.add(this);     // 加入set中addOnlineCount();           // 在线数加1try {sendMessage("conn_success");log.info("有新客户端开始监听,sid=" + userID + ",当前在线人数为:" + getOnlineCount());} catch (IOException e) {log.error("websocket IO Exception");}}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {webSocketSet.remove(this);  // 从set中删除subOnlineCount();              // 在线数减1// 断开连接情况下,更新主板占用情况为释放log.info("释放的sid=" + userID + "的客户端");releaseResource();}private void releaseResource() {// 这里写释放资源和要处理的业务log.info("有一连接关闭!当前在线人数为" + getOnlineCount());}/*** 收到客户端消息后调用的方法** @Param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session session) {log.info("收到来自客户端 sid=" + userID + " 的信息:" + message);// 群发消息HashSet<String> sids = new HashSet<>();if(this.touserID.equals("1")){for (WebSocketServer item : webSocketSet) {sids.add(item.userID);}}else {log.info("推送到:"+this.touserID);sids.add(this.touserID);}try {sendMessage(message, sids);} catch (IOException e) {e.printStackTrace();}}/*** 发生错误回调*/@OnErrorpublic void onError(Session session, Throwable error) {log.error(session.getBasicRemote() + "客户端发生错误");error.printStackTrace();}/*** 群发自定义消息*/public static void sendMessage(String message, HashSet<String> toSids) throws IOException {log.info("推送消息到客户端 " + toSids + ",推送内容:" + message);JSONObject jsonObject = JSONObject.parseObject(message);//webSocketSet.get();for (WebSocketServer item : webSocketSet) {try {//这里可以设定只推送给传入的sid,为null则全部推送if (toSids.size() <= 0) {item.sendMessage(jsonObject.getString("msg"));} else if (toSids.contains(item.userID)) {item.sendMessage(jsonObject.getString("msg"));}} catch (IOException e) {continue;}}}/*** 实现服务器主动推送消息到 指定客户端*/public void sendMessage(String message) throws IOException {this.session.getBasicRemote().sendText(message);}/*** 获取当前在线人数** @return*/public static int getOnlineCount() {return onlineCount.get();}/*** 当前在线人数 +1** @return*/public static void addOnlineCount() {onlineCount.getAndIncrement();}/*** 当前在线人数 -1** @return*/public static void subOnlineCount() {onlineCount.getAndDecrement();}/*** 获取当前在线客户端对应的WebSocket对象** @return*/public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {return webSocketSet;}
}

pom.xml依赖添加

<!--websocket依赖包添加-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-websocket</artifactId><version>5.3.12</version>
</dependency>
<!--日志依赖添加-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version>
</dependency>

index.html页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<script src="JS/index.js" type="text/javascript"></script>
<link rel="stylesheet" href="CSS/style.css" type="text/css">
<style>body{margin: 0px;margin: 0px;background-image: url("image/bk-login.png")}
</style>
<body>
<div align="center">你的账户号<input type="text" id="userID" value="528409336">接受者账户号<input type="text" id="touserID" value="2995460432"><input type="button" onclick="con()" value="连接对方"><hr><table class="table"><tr><td><input type="text" value="78269" style="display: none" id="accentID"><div style="height: 560px"><div id="accentinformation"></div><div id="div"></div></div></td></tr></table><table><tr><td><textarea id="text"></textarea></td><td><input type="button" style="width: 100px;height: 40px;background: #31acfb;border: none" onclick="send()" value="发送"></td></tr></table>
</div>
</body>
</html>
<script type="text/javascript">var websocket = null;function con(){//判断当前websocket是否处于连接状态try {if(websocket.readyState==1){websocket.close();}}catch (e){}var userID=document.getElementById("userID").value;var touserID =document.getElementById("touserID").value;//判断当前浏览器是否支持WebSocketif ('WebSocket' in window) {websocket = new WebSocket("ws://localhost:8066/api/websocket/" + userID+"/"+touserID);// 改成你的地址} else {alert('当前浏览器 Not support websocket')}//连接发生错误的回调方法websocket.onerror = function () {};//连接成功建立的回调方法websocket.onopen = function () {document.getElementById("accentinformation").innerHTML ="";}//接收到消息的回调方法websocket.onmessage = function (event) {var str = event.data;jieshou(str);}}//连接关闭的回调方法websocket.onclose = function () {alert("websocket.onclose: WebSocket连接关闭");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function () {closeWebSocket();}//关闭WebSocket连接function closeWebSocket() {websocket.close();alert('websocket.close: 关闭websocket连接')}//发送消息function send() {var message = document.getElementById('text').value;try {websocket.send('{"msg":"' + message + '"}');fasong(message);} catch (err) {console.error("websocket.send: " + message + " 失败");}}
</script>

CSS代码:style.css(注意css代码文件放在index.html同级下的CSS【大写】文件夹中)

#div{width: 600px;height: 500px;}
#div div{width:100%;display: inline-block;padding: 0px;}
#div img{width: 40px;height: 40px}
#div li{list-style: none}
.right{float: right;}
.left{float: left}
.left,.right{padding: 10px;}
.left li,.right li{display: inline-table}
.div ul{padding: 0px;margin: 0px}
#text{width: 260px;height: 54px}
#frinddiv,#text,#div{overflow:auto;resize:none}
#frinddiv::-webkit-scrollbar,#text::-webkit-scrollbar,#div::-webkit-scrollbar{width: 1px;}
#frinddiv::-webkit-scrollbar-thumb,#text::-webkit-scrollbar-thumb,#div::-webkit-scrollbar-thumb{background: #31acfb}
.cueright,.cueleft{border-radius: 10px;}
.cueright p,.cueleft p{margin:5px}
.cueleft{background:#31acfb}
.cueright{background: #cccccc}
.table{padding: 0px;margin: 0px;border-collapse: collapse; border: aliceblue 1px solid}
#frinddiv{width: 300px;height: 560px;}
#frinddiv ul:hover{background: #cccccc}
#frinddiv li{list-style: none;padding: 0px;margin: 0px}
.friendul li{display: inline-table;}
.friendul img{width: 40px;height: 40px;float: left}
.xuanze li{display: inline-table;margin: 0px}
.xuanze span{display: inline-block;margin: 0px}
.spanfl{border-radius:10px;text-align:center;float:right;margin-top: 5px;margin-right: 5px;background: #f11d38;font-size: 4px;width: 15px;height: 15px;}

javascript文件 index.js(注意index.js文件放在index.html同级下的JS【大写】文件夹中)

function fasong(data){var str = document.getElementById("text");var div = document.getElementById("div");if(str.value!=""){var str0="";var count=0;var str1 = Array.from(data);for(var i=0;i<str1.length;i++){if(i>25){str0 +="<br/>"i=0;}if(count==str1.length){break;}str0+=str1[count];count++;}div.innerHTML +="<div class='div'>"+"<ul class='right'>"+"<li class='cueright'><p>"+str0+"</p></li>"+"<li><img src='image/headg.png''></li>"+"</ul>"+"</div>";}div.scrollTop = div.scrollHeight;document.getElementById("text").value =""
}
function jieshou(data){var div = document.getElementById("div");var str0="";var count=0;var str1 = Array.from(data);for(var i=0;i<str1.length;i++){if(i>25){str0 +="<br/>"i=0;}if(count==str1.length){break;}str0+=str1[count];count++;}div.innerHTML +="<div class=\"div\">\n" +"        <ul class=\"left\">\n" +"            <li><img src='image/headg.png'></li>\n" +"            <li class=\"cueleft\"><p>"+str0+"</p></li>\n" +"        </ul>\n" +"    </div>";document.getElementById("text").value =""div.scrollTop = div.scrollHeight;
}


项目最终运行效果图,该项目中有三张图片没有上传,如有需要自行上网搜索使用自己喜欢的替换即可
欢迎大家github源码项目下载地址更多学习资料加QQ(528409336)

springboot框架下利用websocket实现即时通讯相关推荐

  1. 基于springboot+h5+websocket的即时通讯客服系统和百度实时语音转译(语音在线识别)

    本文章由本人原创 下载链接:https://download.csdn.net/download/u014191624/51948075 这是一个基于springboot+h5+websocket的即 ...

  2. SpringCloud工作笔记060---SpringBoot中使用WebSocket实现即时通讯_实现呼叫中心业务封装

    JAVA技术交流QQ群:170933152 ---------------我们主要用这个来转接,呼叫中心发过来的分机电话 呼叫中心:呼叫过程,首先呼叫中心运营商给个,api手册,api会规定,首先登陆 ...

  3. 即时通讯软件测试方法,Linux系统环境下如何使用aMsn即时通讯

    Linux系统环境下如何使用aMsn即时通讯 发表于:2007-05-26来源:作者:点击数: 标签: [分享] Linux 下使用aMsn详解 amsn这一款在 linux 下的Msn就不多介绍了, ...

  4. STM32F103C8T6基于Arduino框架下利用定时器跑RBG灯闪烁

    STM32F103C8T6基于Arduino框架下利用定时器跑RGB灯闪烁

  5. SpringBoot框架下使用Servlet

    SpringBoot框架下使用Servlet 创建一个Servlet继承HttpServlet 在web.xml配置文件中使用servlet servlet-mapping 1. 第一种方式:注解的方 ...

  6. Websocket实现即时通讯

    前言 关于我和WebSocket的缘:我从大二在计算机网络课上听老师讲过之后,第一次使用就到了毕业之后的第一份工作.直到最近换了工作,到了一家是含有IM社交聊天功能的app的时候,我觉得我现在可以谈谈 ...

  7. springboot框架下的实时消息推送

    功能实现:在得到新数据后以最快的速度推送到前台.(springboot框架) 0.修改pom文件 加入需要的jar包 <dependency><groupId>org.spri ...

  8. 安卓平台下的音视频即时通讯应用的开发

    现在安卓很是火热,一大堆开发人员在捣鼓安卓平台的开发,相信大家也使用过QQ的语音视频对话功能,但是不知道大家有没有试过自己来开发一个基于安卓平台的音视频即时通讯的应用,这个应用必须能够做到跨平台 兼容 ...

  9. C# WPF Caliburn.Micro框架下利用Mef加载其它项目界面

    01 - 前言 MEF是微软自家的托管可扩展框架,在这里我把它用成了ioc容器.在Caliburn.Micro框架下,view和viewmodel被注入到CompositionContainer容器中 ...

最新文章

  1. LeetCode Remove Element
  2. python进阶:闭包、map/reduce/filter函数、lambda函数、装饰器
  3. 解决<style>无法重写.css文件的问题
  4. oracle监听启动命令6,[转] oracle 监听
  5. 计算机双语论文,计算机双语论文
  6. 加州大学欧文分校 计算机专业,UCI的Computer Science「加州大学欧文分校计算机科学系」...
  7. C语言的静态数组初始化
  8. 同一个项目的同一DLL多版本的兼容问题
  9. 网络安全实验四 防火墙技术的具体应用
  10. html计算100以内偶数和,学习脚本1:计算100以内奇数和和偶数和 (笔记)
  11. 调用python-nmap实现扫描局域网存活主机
  12. 4月第3周业务风控关注 |国家网信办启动小众即时通信工具专项整治
  13. idea使用技巧总结,超实用(2年mac idea使用经验)
  14. 候选码、主码、外码、全码、超码
  15. CAD图层的顺序的调整
  16. 如何让医药行业涌现更多“药神”?
  17. 成人职业教育:知乎、B站、网易“短兵相接”
  18. Json对象转换成Json数组
  19. DVDFab Virtual Drive是一套虚拟DVD/蓝光光驱模拟器。虚拟光驱。
  20. 深度学习寿命预测技术路线

热门文章

  1. 小米 13 系列新品发布会将延期举行;马斯克:和苹果的误解得到了解决;IntelliJ IDEA 2022.3 发布|极客头条
  2. 指数函数和正弦函数相乘
  3. 电子绘画画笔笔刷模式的学习笔记
  4. 专门为某种用途设计的计算机称为,专门为某种用途而设计的计算机,称为( )计算机。...
  5. Python入门基础教程(打印一段文字)
  6. ISO8583报文协议 2013-10-16 10:44 563人阅读 评论(0) 收藏...
  7. Python 基础 之 词云(词的频率统计大小成图)的简单实现(包括图片词云,词云颜色,词的过滤)
  8. 微信扫码登录自定义二维码样式
  9. 回文素数(杭电OJ,不喜欢这个题)
  10. 吃鸡神器!免费送一台新款苹果 iPad