springboot配置websocket

springbootboot配置websocket

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Component
@Slf4j
@ServerEndpoint("/websocketHandler/{userId}")
public class MyWebSocketHandler {/*** 线程安全Map*/private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();/*** Redis触发监听名字*/public static final String REDIS_TOPIC_NAME = "socketHandlerReport";//==========【websocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================@OnOpenpublic void onOpen(Session session, @PathParam(value = "userId") String userId) {try {sessionPool.put(userId, session);log.info("【系统 WebSocket】有新的连接,总数为:" + sessionPool.size());} catch (Exception e) {}}@OnClosepublic void onClose(@PathParam("userId") String userId) {try {sessionPool.remove(userId);log.info("【系统 WebSocket】连接断开,总数为:" + sessionPool.size());} catch (Exception e) {e.printStackTrace();}}/*** ws推送消息** @param userId* @param message*/public void pushMessage(String userId, String message) {for (Map.Entry<String, Session> item : sessionPool.entrySet()) {//userId key值= {用户id + "_"+ 登录token的md5串}if (item.getKey().contains(userId)) {Session session = item.getValue();try {//update-begin-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MUsynchronized (session) {log.info("【系统 WebSocket】推送单人消息:" + message);session.getBasicRemote().sendText(message);}//update-end-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU} catch (Exception e) {log.error(e.getMessage(), e);}}}}/*** ws遍历群发消息*/public void pushMessage(String message) {try {for (Map.Entry<String, Session> item : sessionPool.entrySet()) {try {item.getValue().getAsyncRemote().sendText(message);} catch (Exception e) {log.error(e.getMessage(), e);}}log.info("【系统 WebSocket】群发消息:" + message);} catch (Exception e) {log.error(e.getMessage(), e);}}/*** ws接受客户端消息*/@OnMessagepublic void onMessage(String message, @PathParam(value = "userId") String userId) {if (!"ping".equals(message) && !WebsocketConst.CMD_TOPIC.equals(message)) {log.info("【系统 WebSocket】收到客户端消息:" + message);} else {log.debug("【系统 WebSocket】收到客户端消息:" + message);}//------------------------------------------------------------------------------
//        JSONObject obj = new JSONObject();
//        //业务类型
//        obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_CHECK);
//        //消息内容
//        obj.put(WebsocketConst.MSG_TXT, "心跳响应");
//        this.pushMessage(userId, obj.toJSONString());//------------------------------------------------------------------------------//--------PC端消息推送--------Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息:" + message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}//--------增加APP端消息推送--------Session session_app = sessionPool.get(userId + APP_SESSION_SUFFIX);if (session_app != null && session_app.isOpen()) {try {log.info("【websocket移动端消息】 单点消息:" + message);session_app.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}/*** 配置错误信息处理** @param session* @param t*/@OnErrorpublic void onError(Session session, Throwable t) {log.warn("【系统 WebSocket】消息出现错误");//t.printStackTrace();}//==========【系统 WebSocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================//==========【采用redis发布订阅模式——推送消息】========================================================================================/*** 后台发送消息到redis** @param message*/public void sendMessage(String message) {//log.info("【系统 WebSocket】广播消息:" + message);
//        BaseMap baseMap = new BaseMap();
//        baseMap.put("userId", "");
//        baseMap.put("message", message);
//        jeecgRedisClient.sendMessage(REDIS_TOPIC_NAME, baseMap);}/*** 此为单点消息 redis** @param userId* @param message*/public void sendMessage(String userId, String message) {
//        BaseMap baseMap = new BaseMap();
//        baseMap.put("userId", userId);
//        baseMap.put("message", message);
//        jeecgRedisClient.sendMessage(REDIS_TOPIC_NAME, baseMap);}/*** 此为单点消息(多人) redis** @param userIds* @param message*/public void sendMessage(String[] userIds, String message) {for (String userId : userIds) {sendMessage(userId, message);}}//=======【采用redis发布订阅模式——推送消息】==========================================================================================//1.增加app端标识private String APP_SESSION_SUFFIX = "_app";public void sendOneMessage(String userId, String message) {//--------PC端消息推送--------Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息:" + message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}//--------增加APP端消息推送--------Session session_app = sessionPool.get(userId + APP_SESSION_SUFFIX);if (session_app != null && session_app.isOpen()) {try {log.info("【websocket移动端消息】 单点消息:" + message);session_app.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}
}

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** 开启WebSocket支持*/
@Configuration
@EnableWebSocket
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
public class WebsocketConst {/*** 消息json key:cmd*/public static final String MSG_CMD = "cmd";/*** 消息json key:msgId*/public static final String MSG_ID = "msgId";/*** 消息json key:msgTxt*/public static final String MSG_TXT = "msgTxt";/*** 消息json key:userId*/public static final String MSG_USER_ID = "userId";/*** 消息json key:chat*/public static final String MSG_CHAT = "chat";/*** 消息类型 heartcheck*/public static final String CMD_CHECK = "heartcheck";/*** 消息类型 user 用户消息*/public static final String CMD_USER = "user";/*** 消息类型 topic 系统通知*/public static final String CMD_TOPIC = "topic";/*** 消息类型 email*/public static final String CMD_EMAIL = "email";/*** 消息类型 meetingsign 会议签到*/public static final String CMD_SIGN = "sign";/*** 消息类型 新闻发布/取消*/public static final String NEWS_PUBLISH = "publish";}

项目启动后遇到如下错误:

Invocation of init method failed; nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available

用IDEA启动项目,所报的异常,打jar包服务器上运行则不报,原因是spring boot内带tomcat,tomcat中的websocket会有冲突出现问题。我的解决办法:

注释掉WebSocketConfig中的

    @Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}

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

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

相关文章

计算机网络:网络层 —— IPv4 协议的表示方法及其编址方法

文章目录 IPv4IPv4的表示方法IPv4的编址方法分类编址A类地址B类地址C类地址可指派的地址数量一般不使用的特殊IPv4地址 划分子网编址子网掩码默认子网掩码 无分类编址方法地址掩码斜线记法无分类域间路由选择 CIDR IPv4 IPv4&#xff08;Internet Protocol version 4&#xff…

rtp协议:rtcp包发送和接收规则和报告!

RTCP Packet Send and Receive Rules&#xff1a; 发送和接收 RTCP 包的规则在此列出。允许在多播环境或多点单播环境中运行的实现必须满足第 6.2 节中的要求。这样的实现可以使用本节定义的算法来满足这些要求&#xff0c;或者可以使用其他算法&#xff0c;只要其性能等同或更…

详细解读 CVPR2024:VideoBooth: Diffusion-based Video Generation with Image Prompts

Diffusion Models专栏文章汇总:入门与实战 前言:今天是程序员节,先祝大家节日快乐!文本驱动的视频生成正在迅速取得进展。然而,仅仅使用文本提示并不足以准确反映用户意图,特别是对于定制内容的创建。个性化图片领域已经非常成功了,但是在视频个性化领域才刚刚起步,这篇…

在Excel中如何快速筛选非特定颜色

Excel中的自动筛选是个非常强大的工具&#xff0c;不仅可以筛选内容&#xff0c;而且可以筛选颜色&#xff0c;例如筛选A列红色单元格。但是有时希望筛选除了红色之外的单元格&#xff08;下图右侧所示&#xff09;&#xff0c;其他单元格的填充色不固定&#xff0c;有几种颜色…

【Java】java | logback日志配置 | 按包配置级别

一、概述 日志配置需求&#xff1a; 本地部分包开debug&#xff0c;其他路径走配置&#xff1b;只在本地环境有效 二、logback.xml配置 <!--本地调试&#xff0c;开debug--> <springProfile name"dev"><logger name"cn.hg.demo" level&quo…

什么是元件符号什么是封装

话不多说直接上图 左上角就可以理解为元件的符号&#xff0c;右上角可以理解为元件的封装&#xff0c;右下角是封装得3D图&#xff0c;左下角是真实的芯片。 同时注意我们元件符号的小孔&#xff0c;在封装和焊接时我们可以参照小孔的位置以及对应的引脚。如下图所示&#xff…

网站保护神器,雷池社区版的隐藏文件

SafeLine&#xff0c;中文名 “雷池”&#xff0c;是一款简单好用, 效果突出的 Web 应用防火墙(WAF)&#xff0c;可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注入、命…

2024双十一值得入手的好物推荐,双十一必买好物清单详细攻略分享

随着双十一购物狂欢节的临近&#xff0c;广大消费者又开始了一年一度的购物盛宴&#xff0c;在这个全民狂欢的时刻&#xff0c;如何在众多商品中挑选出真正值得入手的好物&#xff0c;成为了许多人的难题。为了帮助大家在这个双十一期间理性消费&#xff0c;挑选到真正适合自己…

AI图片生成3D物体和2D视频提取3D动画

包括AI图片生成3D物体的网站&#xff1a; 第一个为Artefacts.AIhttps://app.artefacts.ai/starter 第二个为 https://3d.csm.ai/ 以下4个的视频教程连接https://www.youtube.com/watch?vmQQCyzTA_F8 第三个为Tripo AI: Tripo AI for Web 第四个为Meshy AI: Meshy - Free …

驾校管理系统|基于java和小程序的驾校管理系统设计与实现(源码+数据库+文档)

驾校管理系统平台 目录 基于java和小程序的驾校管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#…

江协科技STM32学习- P23 DMA 直接存储器存取

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

数据结构与算法(二叉树)

树 树的概念与结构 1. 树是⼀种非线性的数据结构&#xff0c;它是由 n 个有限结点组成的⼀个具有层次关系的集合。 2. 之所以把它叫做树&#xff0c;是因为它看起来像⼀棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下。 2. 有⼀个特殊的结点&#xff0c;称为根…

【C++ 20进阶(1):模块导入 import】

【C 20进阶&#xff08;1&#xff09;&#xff1a;模块导入 import】 原文&#xff1a;https://blog.csdn.net/weixin_44259356/article/details/143270205 引言 本篇文章为系列文章将着重介绍C20新特性&#xff0c;一是希望可以和大家交流分享&#xff0c;二是也便于自己巩…

HarmonyOS应用开发者基础认证——初级闯关习题参考答案大全

相关文章 HarmonyOS应用开发者中级认证——中级闯关习题参考答案大全 HarmonyOS应用开发者高级认证——高级闯关习题参考答案大全 文章目录 HarmonyOS第一课 HarmonyOS介绍判断题单选题多选题 HarmonyOS第一课 DevEco Studio的使用判断题单选题多选题 HarmonyOS第一课 ArkTS语法…

浅析Android View绘制过程中的Surface

前言 在《浅析Android中View的测量布局流程》中我们对VSYNC信号到达App进程之后开启的View布局过程进行了分析&#xff0c;经过对整个App界面的View树进行遍历完成了测量和布局&#xff0c;确定了View的大小以及在屏幕中所处的位置。但是&#xff0c;如果想让用户在屏幕上看到…

使用 FastGPT 工作流实现 AI 赛博算卦,一键生成卦象图

最近那个男人写的汉语新解火遍了全网&#xff0c;那个男人叫李继刚&#xff0c;国内玩 AI 的同学如果不知道这个名字&#xff0c;可以去面壁思过了。 这个汉语新解的神奇之处就在于它只是一段几百字的提示词&#xff0c;效果却顶得上几千行代码写出来的应用程序。 这段提示词…

面试域——岗位职责以及工作流程

摘要 介绍互联网岗位的职责以及开发流程。在岗位职责方面&#xff0c;详细阐述了产品经理、前端开发工程师、后端开发工程师、测试工程师、运维工程师等的具体工作内容。产品经理负责需求收集、产品规划等&#xff1b;前端专注界面开发与交互&#xff1b;后端涉及系统架构与业…

【STM32-HAL库】火焰传感器(STM32F407ZGT6)(附带工程下载链接)

一、TEMT6000光照强度传感器 火焰传感器是一种能够检测火焰的传感器&#xff0c;它通过检测空气中的特定波长的光线来检测火焰的存在&#xff0c;并输出一个信号来通知系统发生了火灾 工作原理 火焰传感器的工作原理基于光学检测技术。当火焰燃烧时&#xff0c;会产生一些特…

Python 实现 excel 数据过滤(从入门到exe)

一、场景分析 假设有如下一份 excel 数据 shop.xlsx, 写一段 python 程序&#xff0c;实现对于车牌的分组数据过滤。 并以车牌为文件名&#xff0c;把店名输出到 车牌.txt 文件中。 比如 闽A.txt 文件内容为&#xff1a; 小林书店福州店1 小林书店福州店2 二、依赖安装 程序依…

乘云而上,OceanBase再越山峰

一座山峰都是一个挑战&#xff0c;每一次攀登都是一次超越。 商业数据库时代&#xff0c;面对国外数据库巨头这座大山&#xff0c;实现市场突破一直都是中国数据库产业多年夙愿&#xff0c;而OceanBase在金融核心系统等领域的攻坚克难&#xff0c;为产业突破交出一副令人信服的…