当前位置:   article > 正文

WebSocket实现群聊功能、房间隔离

WebSocket实现群聊功能、房间隔离
  • 引用WebSocket相关依赖
 		<dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>4.3.30.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>4.3.30.RELEASE</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 后端代码实现,很简单分为消息封装和消息处理
package com.risen.brain.websocket;

import com.alibaba.fastjson.JSONObject;
import com.risen.brain.websocket.entity.Message;
import com.risen.brain.websocket.entity.MessageData;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Administrator
 */
@ServerEndpoint("/public/xzdnTaskSocket/{platform}/{groupId}/{selfId}")
@Component
public class MessageWebSocket {

    private static Map<String, MessageWebSocket> userMap = new ConcurrentHashMap<>();
    private static Map<String, Set<MessageWebSocket>> roomMap = new ConcurrentHashMap<>();
    private Session session;
    private String selfId;


    //建立连接成功调用
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "platform") String platform, @PathParam(value = "groupId") String groupId, @PathParam(value = "selfId") String selfId) {
        this.session = session;
        this.selfId = selfId;
        userMap.put(selfId, this);
        if (!roomMap.containsKey(groupId)) {
            Set<MessageWebSocket> set = new HashSet<>();
            set.add(userMap.get(selfId));
            roomMap.put(groupId, set);
        } else {
            roomMap.get(groupId).add(this);
        }
        MessageData messageData = new MessageData();
        messageData.setSelfId(selfId);
        messageData.setGroupId(groupId);
        messageData.setPlatform(platform);
        messageData.setType("meta");
        messageData.setDetailType("online");
        System.out.println(selfId + "加入了群聊!");

        Message dataMessage = new Message(selfId + "加入了群聊!");
        messageData.setMessages(Arrays.asList(dataMessage));
        sendMessageTo(messageData, groupId, selfId);

    }

    //关闭连接时调用
    @OnClose
    public void onClose(@PathParam(value = "selfId") String selfId, @PathParam("groupId") String groupId) {
        if (roomMap.containsKey(groupId)) {
            Set<MessageWebSocket> set = roomMap.get(groupId);
            for (MessageWebSocket item : set) {
                if (item.selfId.equals(selfId)) {
                    set.remove(item);
                }
            }
        }
    }

    //收到客户端信息
    @OnMessage
    public void onMessage(String message, @PathParam(value = "platform") String platform, @PathParam(value = "selfId") String selfId, @PathParam("groupId") String groupId) {
        MessageData messageData = new MessageData();
        List<Message> objects = new ArrayList<>();
        Message mg = new Message();
        mg.setData(message);
        mg.setType("text");
        objects.add(mg);
        messageData.setMessages(objects);
        messageData.setPlatform(platform);
        sendMessageTo(messageData, groupId, selfId);
        //根据bean名称获取对象,可以对消息进行记录
        //IXzdnInvestigateCityService xzdnInvestigateCityService1 = SpringUtil.getBean("xzdnInvestigateCityService");
        //XzdnInvestigateCity city = new XzdnInvestigateCity();
        //List<Map> groupCityCount = xzdnInvestigateCityService1.findGroupCityCount(city);
        System.out.println("2222");
        /*TableDynaModel tableDynaModel = tableDynaDao.newDynaModel("xzdn_task_message_info");
        tableDynaModel.set("xzdnMessageId", messageData.getId());
        tableDynaModel.set("xzdnMessagePlatform", messageData.getPlatform());
        tableDynaModel.set("xzdnMessageSelfid", messageData.getSelfId());
        tableDynaModel.set("xzdnMessageSelfname", messageData.getSelfName());
        tableDynaModel.set("xzdnMessageSelfdeptid", messageData.getSelfDeptId());
        tableDynaModel.set("xzdnMessageSelfdeptname", messageData.getSelfDeptName());
        tableDynaModel.set("xzdnMessageTime", messageData.getTime());
        tableDynaModel.set("xzdnMessageType", messageData.getType());
        tableDynaModel.set("xzdnMessageDetailtype", messageData.getDetailType());
        tableDynaModel.set("xzdnMessageMessagetype", messageData.getMessageType());
        tableDynaModel.set("xzdnMessageGroupid", messageData.getGroupId());
        tableDynaModel.set("xzdnMessageMessages", JSONObject.toJSONString(messageData.getMessages()));
        tableDynaDao.save(tableDynaModel);*/
    }

    //错误时调用
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("发生错误");
        throwable.printStackTrace();
    }

    /**
     * 群聊
     *
     * @param message 消息
     * @param groupId 房间号
     * @param selfId  发送人
     */
    public static void sendMessageTo(MessageData message, String groupId, String selfId) {
        message.setGroupId(groupId);
        message.setSelfId(selfId);
        if (roomMap.containsKey(groupId)) {
            for (MessageWebSocket item : roomMap.get(groupId)) {
                //if (!item.selfId.equals(selfId)) {
                    item.session.getAsyncRemote().sendText(JSONObject.toJSONString(message));
               // }
            }
        }
    }

    /**
     * 私聊
     *
     * @param message  消息
     * @param toSelfId 接收人
     */
    public void sendUserTo(String message, String toSelfId) {
        if (userMap.containsKey(toSelfId)) {
            userMap.get(toSelfId).session.getAsyncRemote().sendText(message);
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 消息封装,里面包含房间信息,用户信息、消息
package com.risen.brain.websocket.entity;

import lombok.Data;

@Data
public class Message {
    /**
     * 消息类型 text,json,image,audio,video,file,markdown,btn
     */
    private String type;
    /**
     * 内容 媒体类容均为文件id/url/详情json
     */
    private String data;

    public Message() {

    }

    public Message(String data) {
        this.data = data;
        this.type = "text";
    }
}

package com.risen.brain.websocket.entity;

import com.risen.brain.utils.SequenceUtils;
import lombok.Data;

import java.math.BigInteger;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *  * @Author: yxz
 * @Date: 2021/10/18/10:21
 * @Description:
 */
@Data
public class MessageData {
    /**
     * 事件唯一标识符
     */
    private BigInteger id;

    /**
     * 实现平台名称,协议名称 web,dd
     */
    private String platform;
    /**
     * 消息发送人 id
     */
    private String selfId;
    /**
     * 消息发送人
     */
    private String selfName;
    /**
     * 消息发送人部门id
     */
    private String selfDeptId;
    /**
     * 消息发送人部门
     */
    private String selfDeptName;
    /**
     * 事件发生时间(Unix 时间戳),单位:秒
     */
    private Long time;
    /**
     * 事件类型,必须是 meta、message、notice、request 中的一个,分别表示元事件、消息事件、通知事件和请求事件
     */
    private String type;

    /**
     * 事件详细类型
     * meta: online,heartbeat 分别表示 首次连接,心跳包
     * message:
     * notice: remove 删除通知
     * request:
     */
    private String detailType;

    /**
     * 消息类型 1:群消息
     */
    private String messageType;
    /**
     * 群消息时的群id
     */
    private String groupId;

    /**
     * 消息段
     */
    private List<Message> messages;

    public MessageData() {
        this.id = SequenceUtils.nextId();
        this.time = LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 前端代码实现,本人不是专业前端,网上随便找个了页面做交互
<!DOCTYPE HTML>
<html>

<head>
    <meta charset="UTF-8">
    <title>My WebSocket</title>
    <style>
        #message {
            margin-top: 40px;
            border: 1px solid gray;
            padding: 20px;
        }
    </style>
</head>

<body>
<button onclick="conectWebSocket()">连接WebSocket</button>
<button onclick="closeWebSocket()">断开连接</button>
<hr />
<br />
消息:<input id="text" type="text" />
<button onclick="send()">发送消息</button>
<div id="message"></div>
</body>
<script type="text/javascript">

    //获取地址栏参数,key:参数名称



    const urlParams = new URLSearchParams(window.location.search);
    //发信息用户
    const user = urlParams.get('user');
    //房间名称
    const type = urlParams.get('group');

    var websocket = null;

    function conectWebSocket() {
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
            websocket = new WebSocket("ws://localhost:8081/xzdn/public/xzdnTaskSocket/web/"+type+"/"+user);
        } else {
            alert('Not support websocket')
        }

        //连接发生错误的回调方法
        websocket.onerror = function () {
            setMessageInnerHTML("error");
        };

        //连接成功建立的回调方法
        websocket.onopen = function (event) {
            setMessageInnerHTML("tips: 连接成功!");
        }

        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            setMessageInnerHTML(event.data);
        }

        //连接关闭的回调方法
        websocket.onclose = function () {
            setMessageInnerHTML("tips: 关闭连接");
        }

        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            websocket.close();
        }

    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }


    //关闭连接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send() {
        var message = document.getElementById('text').value;
        websocket.send(message,"web",user,type);
    }

</script>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 最终效果

超人发送信息:房间号:加班放假

chao在这里插入图片描述

王亮在房间“加班放假”中,收到了超人信息,并进行回答

在这里插入图片描述

四环单独在“吃喝玩乐”房间并没有收到房间“加班放假”中的消息
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/819932
推荐阅读
相关标签
  

闽ICP备14008679号