WebSocket消息推送
创建WebSocket工具类
package org.jmis.riskassess.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@Component
@ServerEndpoint(value = "/message-service")
public class WebSocketUtil {private static final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();private static final Logger logger = LoggerFactory.getLogger(WebSocketUtil.class);public static void pushMessage(String userId, String message) {Session session = sessions.get(userId);if (session != null && session.isOpen()) {try {session.getBasicRemote().sendText(message);} catch (IOException e) {logger.error("Failed to send message to userId: " + userId, e);}} else {// 会话失效,从会话集合中移除sessions.remove(userId, session);
// logger.warn("Session is invalid for userId: " + userId + ", removing from sessions");}}@OnOpenpublic void onOpen(Session session, EndpointConfig config) {Map<String, List<String>> queryParams = session.getRequestParameterMap();String userId = queryParams.get("userId").get(0);sessions.put(userId, session);logger.info("WebSocket opened: " + session.getId() + ", userId: " + userId);}@OnClosepublic void onClose(Session session) {String closedSessionId = session.getId();sessions.entrySet().removeIf(entry -> entry.getValue().getId().equals(closedSessionId));logger.info("WebSocket closed: " + closedSessionId);}@OnMessagepublic void onMessage(String message, Session session) {String userId = (String) session.getUserProperties().get("userId");if (userId == null) {session.getUserProperties().put("userId", message);logger.info("User ID saved: " + message);}}public static int getSessionCount() {return sessions.size();}public static int getOpenConnectionCount() {int openConnectionCount = 0;for (Session session : sessions.values()) {if (session.isOpen()) {openConnectionCount++;}}return openConnectionCount;}public static List<Session> getOpenConnections() {List<Session> openConnections = new ArrayList<>();for (Session session : sessions.values()) {if (session.isOpen()) {openConnections.add(session);}}return openConnections;}
}
创建WebSocket配置文件
package org.jmis.riskassess.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
业务逻辑
package org.jmis.riskassess.safeSystemDataTask;import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jmis.riskassess.config.WebSocketUtil;
import org.jmis.riskassess.entity.Message;
import org.jmis.riskassess.entity.MessageUser;
import org.jmis.riskassess.pojo.MessageInfo;
import org.jmis.riskassess.pojo.MineFoundation;
import org.jmis.riskassess.service.IMessageService;
import org.jmis.riskassess.service.IMessageUserService;
import org.jmis.riskassess.vo.AlarmRealtimeVO;
import org.jmis.riskassess.vo.DzAlarmAcceptVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springjmis.core.tool.utils.Func;
import org.springjmis.core.tool.utils.ObjectUtil;import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@Component
public class MessagePushTask {@Autowiredprivate WebSocketUtil webSocketUtil;@Autowiredprivate IMessageUserService messageUserService;@Autowiredprivate IMessageService messageService;@Scheduled(fixedDelay = 10000) // 每10秒执行一次public void pushUnreadMessages() {// 查询未读消息的用户以及消息内容List<Map<String,Object>> userIds = messageUserService.findUsersWithUnreadMessages();// 推送未读消息给相应的用户for (Map<String, Object> user : userIds) {Long idLong = (Long) user.get("id");String id = String.valueOf(idLong);String userId = user.get("user_id").toString();Object isImportant= user.get("is_important");String messageName = (String) user.get("message_name");String details = (String) user.get("details");String messageIdLong = user.get("message_id").toString();String messageId = String.valueOf(messageIdLong);String type = (String) user.get("type");// 构造推送消息的内容JSONObject pushMessage = new JSONObject();pushMessage.put("messageId", messageId);pushMessage.put("messageName", messageName);pushMessage.put("details", details);pushMessage.put("userId", userId);pushMessage.put("type", type);pushMessage.put("isImportant", isImportant);pushMessage.put("id", id);// 将推送消息转换为JSON字符串String jsonMessage = pushMessage.toJSONString();// 推送消息给用户WebSocketUtil.pushMessage(userId, jsonMessage);}}//甲烷报警推送@Scheduled(fixedDelay = 10000) // 每10秒执行一次public void alarmMessages() {// 查询未读消息的用户以及消息内容List<AlarmRealtimeVO> alarmRealtimeVOS = messageUserService.alarmMessages();// 推送未读消息给相应的用户for (AlarmRealtimeVO realtimeVO : alarmRealtimeVOS) {String id = realtimeVO.getAlarmid();String userId = realtimeVO.getUserId();String messageName = "超限报警";String details = "报警类型:"+realtimeVO.getAlarmType()+","+"测点类型:"+realtimeVO.getSensorname()+","+"报警地点:"+realtimeVO.getNodeplace()+","+"报警开始时间:"+realtimeVO.getStartTime()+","+"报警持续时长:"+realtimeVO.getTimeLong()+","+"报警最大值:"+realtimeVO.getMaxdata();saveMessage(id,messageName,details,"jkAlarm");saveMessageUser(id,userId);}}//矿井超员报警推送@Scheduled(fixedDelay = 10000) // 每10秒执行一次public void mineOverAlarmMessages() {// 查询未读消息的用户以及消息内容List<MessageInfo> messageInfos = messageUserService.mineOverAlarmMessages();// 推送未读消息给相应的用户for (MessageInfo realtimeVO : messageInfos) {saveMessage(realtimeVO.getId(),realtimeVO.getMessageName(),realtimeVO.getDetails(),"ryAlarm");saveMessageUser(realtimeVO.getId(),realtimeVO.getUserId());}}//地震报警推送@Scheduled(fixedDelay = 10000) // 每10秒执行一次public void dzAlarmMessages() {// 查询未读消息的用户以及消息内容List<MessageInfo> messageInfos = messageUserService.dzAlarmMessages();// 推送未读消息给相应的用户for (MessageInfo realtimeVO : messageInfos) {String id = realtimeVO.getId();List<String> list = Func.toStrList(realtimeVO.getUserId());String messageName = "地震报警";String details = realtimeVO.getDetails();saveMessage(id,messageName,details,"dzAlarm");for (String s : list) {saveMessageUser(id,s);}}}//天气报警推送@Scheduled(fixedDelay = 10000) // 每10秒执行一次public void tqAlarmMessages() {// 查询未读消息的用户以及消息内容List<MessageInfo> tqAlarmMessages = messageUserService.tqAlarmMessages();// 存入message表和messageUser表for (MessageInfo realtimeVO : tqAlarmMessages) {String id = realtimeVO.getId();List<String> list = Func.toStrList(realtimeVO.getUserId());String messageName = realtimeVO.getMessageName();String details = realtimeVO.getDetails();saveMessage(id,messageName,details,"tqAlarm");for (String s : list) {saveMessageUser(id,s);}}}public void saveMessage(String id ,String messageName,String details,String type){List<String> list = messageService.messageIdList();if (!list.contains(id)){Message message=new Message();message.setMessageId(id);message.setMessageName(messageName);message.setType(type);message.setDetails(details);messageService.save(message);}}public void saveMessageUser(String id,String userId){List<MessageUser> messageUserServiceOne= messageUserService.getMessageUser(id,userId);if (CollectionUtil.isEmpty(messageUserServiceOne)) {MessageUser messageUser = new MessageUser();messageUser.setUserId(userId);messageUser.setMessageId(id);messageUserService.save(messageUser);}}}
相关文章:
WebSocket消息推送
创建WebSocket工具类 package org.jmis.riskassess.config;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component;import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.serve…...
二维码智慧门牌管理系统:让城市管理更智能、便捷
文章目录 前言一、二维码智慧门牌管理系统的特点二、数据集约化与规范化三、管理智能化与长效化四、标识规范化与易维护五、服务多元化与便捷化 前言 随着城市化进程的加速,城市管理面临着越来越多的挑战。为了解决地名地址管理交织错综、地名地址支撑政府管理成效…...
React动态添加标签组件
背景 在前端开发的过程中,一些表单的输入经常需要输入多个内容,如果采用一个输入框逗号分隔的方式,展示起来不是很清晰,一般需要采用标签的方式 需求 可以指定空状态时的标题设置标签颜色每个标签的最大长度(字符数)接口传递的时候的分隔标记(是用逗号,还是其他)直接处理表单,不…...
[Linux]套接字通信
摘于https://subingwen.cn,作者:苏丙榅 侵删 文章目录 1. 套接字-socket1.1 概念1.2 网络协议1.3 socket编程1.3.1 字节序1.3.2 IP地址转换1.3.3 sockaddr 数据结构1.3.4 套接字函数 1.4 TCP通信流程1.4.1 服务器端通信流程1.4.2 客户端的通信流程 1.5 扩展阅读1.5.1 初始化套…...
MySQL的故事——MySQL架构与历史
MySQL架构与历史 文章目录 MySQL架构与历史一、MySQL逻辑架构二、并发控制三、事务四、多版本并发控制(MVCC) 一、MySQL逻辑架构 第一层:连接处理、授权认证、安全等等 第二层:查询解析、分析、优化、缓存以及所有的内置函数。包含跨存储引擎的功能&…...
手写Mybatis:第12章-完善ORM框架,增删改查操作
文章目录 一、目标:完善增删改查二、设计:完善增删改查三、实现:完善增删改查3.1 工程结构3.2 完善增删改查类图3.3 扩展解析元素3.4 新增执行方法3.4.1 执行器接口添加update3.4.2 执行器抽象基类3.4.3 简单执行器 3.5 语句处理器实现3.5.1 …...
【1】DDR---容量计算
1、容量计算 density:芯片容量,bit为单位 depth:地址空间, width:数据位宽 densitydepth*width 2、三星DDR 4Gbit(总容量)256M(地址空间)*16(位宽ÿ…...
YashanDB:潜心实干,数据库核心技术突破没有捷径可走
都说数据库是三大基础软件中的一块硬骨头,技术门槛高、研发周期长、工程要求高,市场长期被几大巨头所把持。 因此,实现突破一直是中国数据库产业的夙愿。自上个世纪80年代起,中国数据库产业走过艰辛坎坷的四十余载,终…...
Talk | ICCV‘23南洋理工大学博士后李祥泰:面向统一高效的视频分割方法设计
本期为TechBeat人工智能社区第528期线上Talk! 北京时间9月6日(周三)20:00,南洋理工大学博士后研究员—李祥泰的Talk已准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “面向统一高效的视频分割方法设计”,他分享了其在视…...
怎样把英语视频字幕翻译成中文
我们知道,随着中外文化交流日益频繁,视频翻译作为一种重要的跨文化交流方式,也越来越受到重视。那么,怎样把英语视频翻译成中文,北京视频翻译哪里比较专业? 据了解,视频翻译是直接将一种语言的音…...
智慧铁路:机车整备场数字孪生
机车整备场是铁路运输系统中的重要组成部分,它承担着机车的维修、保养和整备工作,对保障铁路运输的运维和安全起着至关重要的作用。 随着铁路运输的发展、机车技术的不断进步,以及数字化转型的不断推进,数字孪生技术在机车整备场…...
ImageSharp.Web实战:轻松搭建高效图片服务
很多情况下,在开发如PC、H5、小程序等综合平台的时候,图片的展示是个比较头疼的问题。尤其是有会员功能,会员可以上传图片的平台,更是一件麻烦事。平台展示图片的地方,尺寸是定义好的。但用户不配合,上传的…...
端口扫描-安全体系-网络安全技术和协议
端口扫描-安全体系-网络安全技术和协议 端口扫描信息安全的保证体系和评估方法网络安全技术网络攻击和威胁(重要)网络安全协议 端口扫描 全TCP连接:三次握手 半打开式扫描:前两次握手 FIN扫描:不用建立TCP连接 第三方扫描: 拒绝服务攻击有: 同步包风暴ICMP攻击SNMP攻击 都是修改…...
C# wpf 实现截屏框热键截屏功能
wpf截屏系列 第一章 使用GDI实现截屏 第二章 使用DockPanel制作截屏框 第三章 实现截屏框热键截屏(本章) 第四章 实现截屏框实时截屏 第五章 使用ffmpeg命令行实现录屏 文章目录 wpf截屏系列前言一、实现步骤1、响应热键2、截屏显示(1&#…...
springboot + activiti实现activiti微服务化
概述 本文介绍如何将springbootactiviti进行整合,并配合eureka,zuul和feign实现activiti的微服务化,将流程控制和业务逻辑分离. 并实现了几个比较特殊的功能,比如时间段委托(某人请假或出差,出差时间内,所有待办交给被委托人处理),比如节点的无限级加签功能(流程本身有不确定性…...
c语言练习41:深入理解字符串函数strlen strcpy strcat
深入理解字符串函数strlen strcpy strcat 模拟实现:”strlen strcpy strcat strlen strcat: #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<assert.h> strlen 1.通过指针移动模拟 //int my_strlen(char* str) { // size_t c…...
Vue3+Vue-i18n+I18N ALLY+VSCODE 自动翻译多国语言
ps: 效果图放前面,符合的往下看,不符合的出门右转,希望多多点赞评论支持。 三种语言模式,分别是中文、英文、日文 批量翻译 最后的结果 配置vue-i18n 1、下载安装vue-i18n,9以上的版本。 2、创建对应文件夹 3、对应文件夹中代…...
idea意外退出mac
目录 问题描述 解决过程 问题描述 mac上的idea我很久没用了,之前用的时候还是发布新版的开源项目,这几天再用的时候,就出现了idea意外退出的问题,我上网查找了很久,对于我的问题都没有很好的解决。 解决过程 在寻求…...
百度智能云千帆大模型平台2.0来了!从大模型到生产力落地的怪兽级平台!!
目录 前言 最佳算力效能为企业降低门槛 最多大模型,最多数据集为企业保驾护航 企业级安全对于企业来说是硬性要求 前言 普通人或许感知不明显,但是对于企业而言,身处AI时代,是否选择投资大模型,是否拥抱人工智能…...
k8s nfs-client 添加挂载参数 —— 筑梦之路
背景介绍 为什么要使用noresvport参数挂载NAS?不重新挂载会有什么后果? 如果发生网络切换或者后端服务的HA倒换,小概率会造成NFS文件系统阻塞,那就可能需要几分钟时间连接才会自动恢复,极端情况下甚至需要重启ECS才能恢…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
