websocket点对点消息推送

原创 小尘哥 小尘哥 2024年09月10日 21:33 河南

点击蓝字,关注我们

上一篇写了《若依(ruoyi)使用websocket推送数据到前》,猿友指出缺少身份识别,无法精准命中给谁推送,本文来继续解决这个问题。

图片

既然想知道消息推送给谁,那肯定需要知道发送者、接受者、消息内容,三个最基本的东西,我简单定义为sendUserId、receiveUserId、msg。假设有三个人(路飞、索隆、艾斯)互相发消息,为了方便,我将发送者放到url中,实际项目上使用需要根据各项目情况从token、request等解析获取,这里只聊思路。

01

场景

三个人可以互相发消息,也可以给自己发消息,界面如下,接收到的消息会在“消息接收面板”展示出来。

图片

- 当“路飞”对“索隆”说:跟你说过多少遍不要拿我的帽子!,这时候可以看到,索隆收到了消息,艾斯没有。

图片

- 当“索隆”对“艾斯”说:是你拿了那个家伙的帽子?此时路飞视角是没有收到任何消息的

图片

02

实现--添加websocket依赖

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

03

实现-添加配置

@Configuration@EnableWebSocketpublic class WebSocketConfig {
    @Bean    public ServerEndpointExporter serverEndpointExporter() {        return new ServerEndpointExporter();    }
}      

04

实现--消息体

@Datapublic class MsgEntity implements Serializable {
    String msg;
    String userId;
    String receiveUserId;}

05

实现--点对点发送

@Component@ServerEndpoint(value = "/mos/websocket/{userId}")@Slf4jpublic class WebSocket {    private static Map<String, Session> livingSession = new ConcurrentHashMap<>();
    /**     * 客户端与服务端连接成功     *     * @param session     */    @OnOpen    public void onOpen(Session session, @PathParam("userId") String userId) {        livingSession.put(userId, session);    }
    /**     * 客户端与服务端连接关闭     *     * @param session     */    @OnClose    public void onClose(Session session, @PathParam("userId") String userId) {        livingSession.remove(userId);    }
    /**     * 客户端与服务端连接异常     *     * @param error     * @param session     */    @OnError    public void onError(Throwable error, Session session) {        error.printStackTrace();    }
    /**     * 客户端向服务端发送消息     * 主要消息发送在这里,找到接受者的session,并推送消息内容     * @param message     * @throws IOException     */    @OnMessage    public void onMsg(String msg) throws IOException {        MsgEntity msgEntity = JSONUtil.toBean(msg,MsgEntity.class);        Session session = livingSession.get(msgEntity.getReceiveUserId());        session.getAsyncRemote().sendText(msgEntity.getMsg());    }
}

06

实现--前端

前端为了界面稍微好看一些,使用了layui,无论什么都是相通的,vue、jquery都可以。

<!DOCTYPE HTML><html xmlns:th="http://www.thymeleaf.org"><head>    <title>socket消息推送</title>    <div th:replace="~{common/links::header}"></div>    <div th:replace="~{common/script::js_footer}"></div></head><body><div class="layui-bg-gray" style="padding: 16px;">    <div class="layui-row layui-col-space15">        <div class="layui-col-md6">            <div class="layui-card">                <div class="layui-card-header">消息发送面板(发送人:<span id="sender"></span>)</div>                <div class="layui-card-body">                    <form class="layui-form layui-form-pane" id="searchForm">                        <div class="layui-form-item" pane>                            <label class="layui-form-label">发送给</label>                            <div class="layui-input-block">                                <input type="radio" name="receiveUserId" value="路飞" title="路飞" checked>                                <input type="radio" name="receiveUserId" value="索隆" title="索隆">                                <input type="radio" name="receiveUserId" value="艾斯" title="艾斯">                            </div>                        </div>                        <div class="layui-form-item layui-form-text">                            <div class="layui-input-block">                                <textarea placeholder="请输入需要发送的消息" class="layui-textarea" name="msg" ></textarea>                            </div>                        </div>                        <div class="layui-form-item">                            <button class="layui-btn" lay-submit="" lay-filter="add" >发送消息</button>                        </div>                    </form>                </div>            </div>        </div>        <div class="layui-col-md6">            <div class="layui-card">                <div class="layui-card-header">消息接收面板</div>                <div class="layui-card-body">                    <span id="content"></span>                </div>            </div>        </div>    </div></div>


</body><script th:inline="javascript">    layui.use('form', function () {
        var $ = layui.jquery,form = layui.form;        const urlParams = new URLSearchParams(window.location.search);        const sendUserId = urlParams.get('sendUserId');        const receiveUserId = urlParams.get('receiveUserId');        $("#sender").html(sendUserId)
        form.on('submit(add)', function (data) {            let param = {userId:sendUserId}            Object.assign(param,data.field);            Common.ajaxFormSubmit('/websocket/send', param, function (data) {                layer.msg('消息已发送')            });            return false;        });        let webSocket = null;        if ('WebSocket' in window){            webSocket = new WebSocket("ws://localhost:8888/mos/websocket/"+sendUserId);        }else{            layer.msg('您的浏览器不支持websocket')        }        webSocket.onopen = function () {            layer.msg('连接成功')        }        webSocket.onerror = function (error) {            layer.msg('连接失败',error)        }        webSocket.onclose = function () {            layer.msg('连接关闭')        }        webSocket.onmessage = function (event) {            $("#content").html(event.data)        }
    });</script></html>

07

其他说明

1. 没有进行鉴权,需要视具体项目情况而定

2. 默认三个会话都已创建,否则会报“ because "session" is null”的错,只是简单演示使用,实际项目可能还需要考虑接收方离线时怎么办等等。

3. 代码已上传gitee,需要的童鞋可以自行获取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值