😎 先看效果
一人分饰多角(bushi)

😏 后端代码
🍗 先引入websocket依赖
<!-- websocket消息推送 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
讯享网
🍗🍗 添加 WebSocketConfig 配置
讯享网import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfig {
@Bean public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter(); } }
🍗🍗🍗 实体bean接收客户端发过来的信息
@Data public class SocketMsg {
/ * 聊天类型 0 群聊 1 单聊 / private int type; / * 发送者 / private String sendOutUser; / * 接受者 / private String receiveUser; / * 消息 / private String msg; }
🍗🍗🍗🍗 WebSocketUtil
讯享网import cn.hutool.json.JSONUtil; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; / * WebSocket 连接测试 */ @Component @ServerEndpoint("/web-socket/{userName}") public class WebSocketUtil {
private String userName; private Session session; / 固定前缀 */ private static final String USER_NAME_PREFIX = "user_name_"; / * 用来存放每个客户端对应的MyWebSocket对象。 / private static CopyOnWriteArraySet<WebSocketUtil> webSocketSet = new CopyOnWriteArraySet<>(); / * 存放Session集合,方便推送消息 (javax.websocket.Session) */ private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>(); / * 私聊:向指定客户端推送消息 */ public synchronized static void privateMessage(SocketMsg socketMsg) {
//接收消息的用户 Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser()); //发送给接收者 if(receiveUser != null){
//发送给接收者 System.out.println(socketMsg.getSendOutUser()+" 向 "+socketMsg.getReceiveUser()+" 发送了一条消息:"+socketMsg.getMsg()); receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser()+":"+socketMsg.getMsg()); }else{
//发送消息的用户 System.out.println(socketMsg.getSendOutUser()+" 私聊的用户 "+socketMsg.getReceiveUser()+" 不在线或者输入的用户名不对"); Session sendOutUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getSendOutUser()); //将系统提示推送给发送者 sendOutUser.getAsyncRemote().sendText("系统消息:对方不在线或者您输入的用户名不对"); } } / * 群聊:公开聊天记录 * @param userName 发送者的用户名称(当前用户) * @param message 发送的消息 * @param flag 用来标识 是否要将消息推送给 当前用户 */ public synchronized static void publicMessage(String userName,String message,boolean flag) {
for (WebSocketUtil item : webSocketSet) {
Session session = item.session; if (flag){
session.getAsyncRemote().sendText(message); }else {
//获取发送这条消息的用户 Session currentUser = sessionMap.get(USER_NAME_PREFIX + userName); //消息不用推送到发送者的客户端 if (!session.getId().equals(currentUser.getId())){
session.getAsyncRemote().sendText(message); } } } System.out.println("公共频道接收了一条消息:"+message); } / * 监听:连接成功 * @param session * @param userName 连接的用户名 */ @OnOpen public void onOpen(Session session, @PathParam("userName") String userName) {
this.userName = userName; this.session = session; sessionMap.put(USER_NAME_PREFIX + userName, session); webSocketSet.add(this); //在线数加1 String tips = userName+" 加入聊天室。当前聊天室人数为" + webSocketSet.size(); System.out.println(tips); publicMessage(userName,tips,true); } / * 监听:收到客户端发送的消息 * @param message 发送的信息(json格式,里面是 SocketMsg 的信息) */ @OnMessage public void onMessage(String message) {
if (JSONUtil.isTypeJSONObject(message)) {
SocketMsg socketMsg = JSONUtil.toBean(message, SocketMsg.class); if(socketMsg.getType() == 1){
//单聊,需要找到发送者和接受者 privateMessage(socketMsg); }else{
//群发消息 publicMessage(socketMsg.getSendOutUser(),socketMsg.getSendOutUser()+": "+socketMsg.getMsg(),false); } } } / * 监听: 连接关闭 */ @OnClose public void onClose() {
if (sessionMap.containsKey(USER_NAME_PREFIX + userName)) {
//连接关闭后,将此websocket从set中删除 sessionMap.remove(USER_NAME_PREFIX + userName); webSocketSet.remove(this); } String tips = userName+" 退出聊天室。当前聊天室人数为" + webSocketSet.size(); System.out.println(tips); publicMessage(userName,tips,true); } / * 监听:发生异常 * @param error */ @OnError public void onError(Throwable error) {
System.out.println("userName为:" + userName + ",发生错误:" + error.getMessage()); error.printStackTrace(); } }
😋 前端代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>聊天室</title> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <style type="text/css"> input{
width: 150px; height: 30px; line-height: 25px; padding: 5px 10px; border-radius: 5px; border: 2px solid; font-size: 16px; } #msg{
width: 300px; } button{
width: 80px; height: 44px; padding: 5px 20px; border-radius: 5px; } </style> </head> <body> 聊天室<br/><br/> <input type="text" id="sendOutUser" placeholder="自己的用户名"> <button onclick="connectWebSocket()">上线</button> <button onclick="closeWebSocket()">下线</button> <br/><br> <input type="text" id="msg" placeholder="要发送的信息"/> <input type="text" id="receiveUser" placeholder="接收人的用户名"/> <button onclick="send()">发送</button> <br><br> <hr> <div id="msgList"></div> <script type="text/javascript"> var websocket = null; //连接WebSocket function connectWebSocket() {
var sendOutUser = document.getElementById("sendOutUser").value; if (sendOutUser === "") {
alert("请输入用户名"); return; } //判断当前浏览器是否支持websocket if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:7070/web-socket/"+document.getElementById("sendOutUser").value); } else {
alert('当前浏览器 not support websocket') } //连接发生错误的回调方法 websocket.onerror = function () {
alert("连接发生错误"); }; //连接成功建立的回调方法 websocket.onopen = function () {
var sendOutUser = document.getElementById("sendOutUser") sendOutUser.readOnly = true sendOutUser.style.backgroundColor='#ddd' } //接收到消息的回调方法 websocket.onmessage = function (event) {
console.log(event.data) innerdiv("",event.data) } //连接关闭的回调方法 websocket.onclose = function () {
innerdiv("","websocket连接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function () {
closewebsocket(); } } //关闭连接 function closeWebSocket() {
websocket.close(); } //发送消息 function send() {
var m = new Map(); // 空Map var sendOutId = document.getElementById("sendOutUser") //发送者 var msg = document.getElementById("msg").value //发送消息 if (msg === "") {
alert("请输入消息"); return; } var receiveUser = document.getElementById("receiveUser").value //接收者 m.set("sendOutUser",sendOutUser.value); m.set("msg",msg) // 接收者为空时,type为群聊,否则为私聊 if (receiveUser === "") {
m.set("type",0) }else{
m.set("receiveUser",receiveUser) m.set("type",1) } json = mapToJson(m) websocket.send(json) innerdiv("我",msg) } //map转换为json function mapToJson(map) {
var obj= Object.create(null); for (var[k,v] of map) {
obj[k] = v; } return JSON.stringify(obj); } //显示聊天记录到页面 function innerdiv(id,txt){
var msgList = document.getElementById("msgList") if (id === "") {
msgList.innerHTML += "<div>" + txt + "</div><br>" }else{
msgList.innerHTML += "<div>"+ id +": "+txt+ "</div><br>" } } </script> </body> </html>
最后
希望大家多多点赞支持一下(不要光收藏不点赞啊呜呜呜)





版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/126819.html