即时通讯 离线消息处理初版

离线消息处理

NotOnlineExecute

package com.example.im.infra.executor.send;import com.example.im.endpoint.WebSocketEndpoint;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.Set;/*** @author PC* 不在线处理方式*/
@Component
public class NotOnlineExecute {private final static Logger logger = LoggerFactory.getLogger(NotOnlineExecute.class);private RedisTemplate<String, String> redisTemplate;@Autowiredpublic void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}/*** 用户不在线时保存离线消息** @param notOnlineReceiverSet 不在线人员列表* @param message              消息*/public void notOnlineMessageSave(Set<String> notOnlineReceiverSet, String message) {//离线消息notOnlineReceiverSet.forEach(receiver -> redisTemplate.opsForSet().add("offline_messages:" + receiver, message));}/*** 用户上线时进行发送** @param receiverName 接收人*/public void sendOnline(String receiverName) {int receiverNameHashCode = receiverName.hashCode();Set<String> messageSet = redisTemplate.opsForSet().members("offline_messages:" + receiverName);if (CollectionUtils.isEmpty(messageSet)) {logger.info(receiverName + "no offline messages");return;}messageSet.forEach(message -> {try {WebSocketEndpoint.WEB_SOCKET_ENDPOINT_MAP.get(receiverNameHashCode).getSession().getBasicRemote().sendText(message);} catch (IOException e) {logger.error("An error occurred when the user: {} received an offline message: {}", receiverName, message);}});redisTemplate.delete("offline_messages:" + receiverName);}
}

com.example.im.infra.executor.send.DefaultSendExecutor#sendToUser

向redis添加未送达消息

notOnlineReceiverSet = notOnlineReceiverSet.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toSet());
if (CollectionUtils.isNotEmpty(notOnlineReceiverSet)) {//处理未送达消息notOnlineExecute.notOnlineMessageSave(notOnlineReceiverSet, generatorMessage(message));logger.info("not online number is " + notOnlineReceiverSet.size());logger.info("The user : {} is not online", String.join(",", notOnlineReceiverSet));
}

com.example.im.endpoint.WebSocketEndpoint#onOpen

用户登录时触发离线消息发送

WEB_SOCKET_ENDPOINT_MAP.put(hashCode, this);
//触发离线消息发送
notOnlineExecute.sendOnline(userName);

测试

test2向test1发送消息,test1不进行连接

test1连接,接收到离线消息

参考资料

[1].处理离线消息代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/882760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle里面,with ... as 用法介绍

在Oracle数据库中&#xff0c;WITH AS 子句&#xff08;也称为公用表表达式&#xff0c;CTE, Common Table Expression&#xff09;是一种在查询中定义临时结果集的方法。这个临时结果集可以在后续的查询中被引用&#xff0c;就像是一个临时的表或视图一样。使用 WITH AS 子句可…

Django学习(三)

Django的设计模式及模板层 传统的MVC&#xff08;例如java&#xff09; Django的MTV 模板层&#xff1a; 模板加载&#xff1a; 代码&#xff1a; views.py def test_html(request):#方案一# from django.template import loader# 1. 使用loader加载模板# t loader.get_…

JAVA使用easyExcel导出数据到EXCEl,导出数据不全问题解决

JAVA使用easyExcel导出数据到EXCEl,导出数据不全问题解决 问题描述解决思路一解决思路二温馨提示 问题描述 JAVA使用easyExcel导出数据到EXCEl,导出数据不全问题。 导出的excel部分列有数据&#xff0c;好几列没有数据 解决思路一 从网上百度查询&#xff0c;大多数的解决思路…

ICP算法理解入门之RT求解

本文仅仅分析了一下两组点云做好匹配好了之后&#xff0c; 如何解算RT&#xff0c; 并不涉及匹配过程&#xff0c;详细的匹配&#xff0c;下次再出一篇博客 ICP 求解旋转矩阵 ( R ) 的步骤 给定两个点云集合 ( P {p_1, p_2, …, p_n} )&#xff08;源点云&#xff09;和 ( Q…

线性可分支持向量机的原理推导 9-29对偶可行性条件 公式解析

本文是将文章《线性可分支持向量机的原理推导》中的公式单独拿出来做一个详细的解析&#xff0c;便于初学者更好的理解。 公式 9-29 是支持向量机&#xff08;SVM&#xff09;优化过程中 Karush-Kuhn-Tucker&#xff08;KKT&#xff09; 条件的一个部分&#xff0c;表示对偶可行…

uniapp-uniapp + vue3 + pinia 搭建uniapp模板

使用技术 ⚡️uni-app, Vue3, Vite, pnpm &#x1f4e6; 组件自动化引入 &#x1f34d; 使用 Pinia 的状态管理 &#x1f3a8; tailwindcss - 高性能且极具灵活性的即时原子化 CSS 引擎 &#x1f603; 各种图标集为你所用 &#x1f525; 使用 新的 <script setup> …

多ip访问多网站

作业要求 配置nginx服务通过ip访问多网站 [rootlocalhost ~]# systemctl stop firewalledFailed to stop firewalled.service: Unit firewalled.service not loaded. [rootlocalhost ~]# mount /dev/sr0 /mnt mount: /mnt: /dev/sr0 已挂载于 /run/media/redhat/RHEL-9-3-0-B…

搜维尔科技:我们用xsens动作捕捉技术制作的数字人

我们用xsens动作捕捉技术制作的数字人 搜维尔科技&#xff1a;我们用xsens动作捕捉技术制作的数字人

云原生技术:nacos进化到servicemash

面试的时候跟面试官吹嘘说&#xff0c;现在主流的微服务架构&#xff0c;都已经用得熟熟的了&#xff0c;自己技术很不错。进了公司却被分到了API资产管理平台&#xff0c;要做一个类似于网关的东西。经过调研才发现&#xff0c;自己用的微服务架构已经过时了&#xff0c;什么&…

Spring配置/管理bean-IOC(控制反转) 非常详细!基于XML及其注解!案例分析! 建议复习收藏!

目录 1.Spring配置/管理bean介绍 2.基于XML配置bean 2.1基于id来获取bean对象 2.2基于类型获取bean对象 2.3通过指定构造器配置bean对象 2.4通过p名称空间配置bean 2.5通过ref配置bean(实现依赖注入) 2.6注入内部Bean对象&#xff0c;依赖注入另一种方式 2.7 注入集合…

骨传导耳机哪款好?五大热门畅销骨传导耳机推荐!

在当今快节奏的生活中&#xff0c;骨传导耳机因其独特的声音传导方式和开放式的佩戴体验&#xff0c;逐渐成为运动爱好者和音乐发烧友的新宠。它们不仅提供了一种更为安全、舒适的听觉享受&#xff0c;还能在运动时让我们保持对周围环境的感知。随着技术的不断进步&#xff0c;…

理解VSCODE基于配置的设置,避免臃肿

这节课我们讲两点&#xff1a; &#xff08;一&#xff09;下载、安装、汉化及美化 VSCODE&#xff1b; &#xff08;二&#xff09;理解VSCODE中基于配置&#xff08;Profiles&#xff09;的设置&#xff08;Settings&#xff09;&#xff0c;让 VSCODE 保持清爽。 &#xff0…

Java:数据结构-二叉树oj题

1.判断两个数是否相同 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; public boolean isSameTree(TreeNode p, TreeNode q) {if(pnull && q!null || qnull && p!null){return false;}if(pnull && qnull){return true;}if(q.val!p.v…

python命令行解析argparse操作

目录 一、使用sys.argv 二、使用argparse模块 更多功能&#xff1a; 三、使用getopt模块 四、使用argparse模块来处理布尔型参数 1.使用store_true和store_false动作 2.自定义布尔型参数的处理 一、使用sys.argv 在python中sys.argv是一个包含命令行参数的列表。其中sy…

跨越数字鸿沟,FileLink文件摆渡系统——您的数据安全高效传输新选择

在这个信息爆炸的时代&#xff0c;数据的流通与共享已成为推动各行各业发展的关键力量。然而&#xff0c;随着数据量的激增&#xff0c;如何在保证数据安全的前提下&#xff0c;实现高效、便捷的文件传输&#xff0c;成为了众多企业和个人用户面临的重大挑战。正是在这样的背景…

zabbix 迁移数据目录

由于安装zabbix的时候数据目录给小了&#xff0c;现在决定迁移数据目录 一&#xff1a;查找数据目录 这个数据目录我们只需要看数据库的配置文件就行&#xff0c;my,cnf datadir指向的就是数据目录 ls /var/lib/mysql/ 二&#xff1a;创建新的数据目录 mkdir /monitor/ …

大数据实验3: HDFS基础编程 (shell命令、JAVA API使用)

实验3&#xff1a; HDFS基础编程 一、实验目的 HDFS的shell命令使用HDFS的JAVA API使用&#xff1b; 二、实验平台 操作系统&#xff1a;Linux&#xff08;Ubuntu16.04&#xff09;&#xff1b;Hadoop版本&#xff1a;3.3.1&#xff1b;JDK版本&#xff1a;1.8&#xff1b;…

C++20中头文件source_location的使用

<source_location>是C20中新增加的头文件&#xff0c;此头文件是utility库的一部分。 主要内容为类std::source_location&#xff1a;表示有关源代码的某些信息&#xff0c;例如文件名(__FILE__)、行号(__LINE__)和函数名(__func__)。 以下为测试代码&#xff1a; names…

Stream流 学习笔记

为了提高程序员对数组和集合的操作便利性而推出的操作--Stream流 1.流的创建 数组用Arrays.stream(数组名)来获取流 集合用集合.stream()来获取流 String [] strings; List list new ArrarList<>(); //数组 stream Arrays.stream(strings) //集合 stream list.stream…

交易之路:如何找到适合自己的交易品种

大部分新手交易者最容易陷入的误区就是盲目跟风&#xff0c;他们倾向于选择那些被众人追捧且看似成功的交易品种&#xff0c;认为既然大家都在做&#xff0c;那么一定有利可图。然而&#xff0c;他们忽略了交易品种选择的核心原则&#xff1a;基于个人的深入测试与理解&#xf…