JAVA Spring WebSocket 实时消息

代码环境:

        jdk8, spring-boot1.5.22

依赖:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.22.RELEASE</version><relativePath /> <!-- lookup parent from repository -->
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- spring-boot的web启动的jar包 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion><exclusion><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></exclusion><exclusion><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId></exclusion><exclusion><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId></exclusion><exclusion><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId></exclusion><exclusion><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId></exclusion></exclusions></dependency></dependencies>

代码:

package cn.com.trinitygo.scm.common.util.websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;/*** websocket的配置类* @ClassName: CustomWebSocketConfig* @Author: peilei* @Date: 2021/9/13 14:59* @Description*/
@Configuration
@EnableWebSocket
public class CustomWebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(customWebSocketHandler(), "/webSocketBySpring/customWebSocketHandler").addInterceptors(new CustomWebSocketInterceptor()).setAllowedOrigins("*");registry.addHandler(customWebSocketHandler(), "/sockjs/webSocketBySpring/customWebSocketHandler").addInterceptors(new CustomWebSocketInterceptor()).setAllowedOrigins("*").withSockJS();}@Beanpublic WebSocketHandler customWebSocketHandler() {return new CustomWebSocketHandler();}
}
package cn.com.trinitygo.scm.common.util.websocket;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;/*** WebSocket握手时的拦截器* @ClassName: CustomWebSocketInterceptor* @Author: peilei* @Date: 2021/9/13 15:00* @Description*/
public class CustomWebSocketInterceptor implements HandshakeInterceptor {private Logger logger = LoggerFactory.getLogger(CustomWebSocketInterceptor.class);/*** 关联HeepSession和WebSocketSession,* beforeHandShake方法中的Map参数 就是对应websocketSession里的属性*/@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception {if (request instanceof ServletServerHttpRequest) {logger.info("*****beforeHandshake******");HttpServletRequest httpServletRequest = ((ServletServerHttpRequest) request).getServletRequest();HttpSession session = httpServletRequest.getSession(true);logger.info("userId:{}", httpServletRequest.getParameter("userId"));if (session != null) {map.put("sessionId",session.getId());map.put("userId", httpServletRequest.getParameter("userId"));}}return true;}@Overridepublic void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {logger.info("******afterHandshake******");}
}
package cn.com.trinitygo.scm.common.util.websocket;import cn.com.trinitygo.scm.service.SysMsgService;
import com.alibaba.fastjson.JSONObject;
import httl.util.StringUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.slf4j.Logger;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;/*** 创建一个WebSocket server** @ClassName: CustomWebSocketHandler* @Author: peilei* @Date: 2021/9/13 14:48* @Description*/
@Service
public class CustomWebSocketHandler extends TextWebSocketHandler implements WebSocketHandler {@AutowiredSysMsgService sysMsgService;private Logger logger = LoggerFactory.getLogger(CustomWebSocketHandler.class);// 在线用户列表private static final Map<String, WebSocketSession> users;// 用户标识private static final String CLIENT_ID = "userId";static {users = new HashMap<>();}@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {logger.info("成功建立websocket-spring连接");String userId = getUserId(session);if (StringUtils.isNotEmpty(userId)) {users.put(userId, session);session.sendMessage(new TextMessage("成功建立websocket-spring连接"));logger.info("用户标识:{},Session:{}", userId, session.toString());}}@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) {logger.info("收到客户端消息:{}", message.getPayload());JSONObject msgJson = JSONObject.parseObject(message.getPayload());String to = msgJson.getString("to");String msg = msgJson.getString("msg");WebSocketMessage<?> webSocketMessageServer = new TextMessage("server:" + message);try {session.sendMessage(webSocketMessageServer);if ("all".equals(to.toLowerCase())) {sendMessageToAllUsers(new TextMessage(getUserId(session) + ":" + msg));} else {sendMessageToUser(to, new TextMessage(getUserId(session) + ":" + msg));}} catch (IOException e) {logger.info("handleTextMessage method error:{}", e);}}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {if (session.isOpen()) {session.close();}logger.info("连接出错");users.remove(getUserId(session));}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {logger.info("连接已关闭:" + status);users.remove(getUserId(session));}@Overridepublic boolean supportsPartialMessages() {return false;}public void sendMessage(String jsonData) {logger.info("收到客户端消息sendMessage:{}", jsonData);JSONObject msgJson = JSONObject.parseObject(jsonData);String userId = StringUtils.isEmpty(msgJson.getString(CLIENT_ID)) ? "陌生人" : msgJson.getString(CLIENT_ID);String to = msgJson.getString("to");String msg = msgJson.getString("msg");if ("all".equals(to.toLowerCase())) {sendMessageToAllUsers(new TextMessage(userId + ":" + msg));} else {sendMessageToUser(to, new TextMessage(userId + ":" + msg));}}/*** 发送信息给指定用户** @param userId* @param message* @return* @Title: sendMessageToUser* @Description: TODO* @Date 2021/9/14 17:33* @author OnlyMate*/public boolean sendMessageToUser(String userId, TextMessage message) {if (users.get(userId) == null)return false;WebSocketSession session = users.get(userId);logger.info("sendMessage:{} ,msg:{}", session, message.getPayload());if (!session.isOpen()) {logger.info("客户端:{},已断开连接,发送消息失败", userId);return false;}try {session.sendMessage(message);} catch (IOException e) {logger.info("sendMessageToUser method error:{}", e);return false;}return true;}/*** 发送信息给指定多用户** @return* @Title: sendMessageToUser* @Description: TODO* @Date 2021/9/14 17:33* @author OnlyMate*/public boolean sendMessageToUsers(Long businessId, Integer type, String cnContent, String enContent, List<Long> ids, Integer businessType, Integer sendType, String tokenUserId) {if (ids != null && ids.size() > 0) {sysMsgService.sendMessage(businessId, type, cnContent, enContent, ids, businessType, sendType, tokenUserId);for (Long userId : ids) {String userIdstr = userId.toString();if (users.get(userIdstr) == null){continue;}WebSocketSession session = users.get(userIdstr);TextMessage message = new TextMessage(cnContent);logger.info("sendMessage:{} ,msg:{}", session, message.getPayload());if (!session.isOpen()) {logger.info("客户端:{},已断开连接,发送消息失败", userIdstr);continue;}try {session.sendMessage(message);} catch (IOException e) {logger.info("sendMessageToUser method error:{}", e);continue;}}}return true;}/*** 广播信息** @param message* @return* @Title: sendMessageToAllUsers* @Description: TODO* @Date 2021/9/14 17:33* @author OnlyMate*/public boolean sendMessageToAllUsers(TextMessage message) {boolean allSendSuccess = true;Set<String> userIds = users.keySet();WebSocketSession session = null;for (String userId : userIds) {try {session = users.get(userId);if (session.isOpen()) {session.sendMessage(message);} else {logger.info("客户端:{},已断开连接,发送消息失败", userId);}} catch (IOException e) {logger.info("sendMessageToAllUsers method error:{}", e);allSendSuccess = false;}}return allSendSuccess;}/*** 获取用户标识** @param session* @return* @Title: getUserId* @Description: TODO* @Date 2021/9/14 17:33* @author OnlyMate*/private String getUserId(WebSocketSession session) {try {String userId = session.getAttributes().get(CLIENT_ID).toString();return userId;} catch (Exception e) {return null;}}
}

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

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

相关文章

C++ (week6、7):Linux系统编程4:网络

文章目录 四、网络和网络编程(一) 网络协议1.基础概念2.网络协议和网络模型&#xff1a;OSI七层模型、TCP/IP四层协议3.TCP协议(1)TCP协议的特点(2)TCP协议的首部格式(3)TCP状态图(4)为什么要三次握手&#xff1f;2次行不行&#xff1f;(5)为什么要四次挥手&#xff1f;(6)快速…

软件测试分类介绍

大家好&#xff0c;软件测试是确保软件质量的关键环节之一&#xff0c;通过对软件系统的各个方面进行测试&#xff0c;可以发现和解决潜在的问题&#xff0c;提高软件的稳定性、可靠性和用户满意度。在软件测试领域&#xff0c;根据测试的目的、方法和对象的不同&#xff0c;可…

什么是BMS?电池管理系统(BMS)到底在管理哪些东西?

BMS是电池管理系统&#xff08;Battery Management System&#xff09;的缩写。 它是一种用于管理和监控电池组的系统&#xff0c;通过监测电池状态、控制充放电过程、保护电池安全等功能&#xff0c;确保电池组的安全、稳定和高效运行。 BMS通常应用于电动汽车、储能系统、航…

Python业务规则引擎库之rules使用详解

概要 在软件开发中,业务规则引擎是一种重要的工具,可以帮助开发者将复杂的业务逻辑从代码中解耦出来,并以更直观的方式进行管理和维护。rules 是一个轻量级的 Python 库,专门用于定义和执行业务规则。它提供了一种简洁且强大的方式来管理应用程序中的规则逻辑,使代码更加…

C++ 引用 - 引用的特点|在优化程序上的作用

引用是C 的一个别名机制&#xff0c;所谓别名&#xff0c;就是同一块内存共用多个名字&#xff0c;每个名字都指的是这片空间&#xff0c;通过这些别名都能访问到同样的一块空间。 就像鲁迅和周树人是同一个人。 ——鲁迅 一、引用的基本用法 int a 10; int& ref a; // …

Kafka之ISR机制的理解

文章目录 Kafka的基本概念什么是ISRISR的维护机制ISR的作用ISR相关配置参数同步过程示例代码总结 Kafka中的ISR&#xff08;In-Sync Replicas同步副本&#xff09;机制是确保数据高可用性和一致性的核心组件。 Kafka的基本概念 在Kafka中&#xff0c;数据被组织成主题&#xf…

巴中青少年编程:开启未来科技的无限可能

巴中青少年编程&#xff1a;开启未来科技的无限可能 在数字化时代&#xff0c;编程已成为一项重要的技能&#xff0c;而巴中的青少年们正积极投身其中&#xff0c;探索编程的奥秘。那么&#xff0c;巴中青少年编程究竟有什么用处呢&#xff1f;本文将从四个方面、五个方面、六…

Django序列化器详解:普通序列化器与模型序列化器的选择与运用

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

充电桩出口:跨国贸易的机遇与挑战之旅

在新能源浪潮席卷全球的今天&#xff0c;充电桩作为电动汽车的“加油站”&#xff0c;正逐渐从幕后走向台前。 而在这场跨国贸易的舞台上&#xff0c;充电桩的出口之路&#xff0c;既充满了诱人的机遇&#xff0c;也伴随着不小的挑战。 机遇&#xff0c;源自日益增长的全球市场…

免费听歌,电脑或手机免费听歌,落雪音乐安装详细步骤

近年来&#xff0c;由于资本的力量导致各种收费&#xff0c;看个电视想听歌都必须要付费了&#xff0c;否则你听不完整&#xff0c;吃相非常难看&#xff0c;特别是电视&#xff0c;吸血鬼式吸收各种会员费&#xff0c;各种APP也是铺天盖地的广告&#xff0c;渐渐迷失了自我&am…

JSP设计理念并没有过时

在JSP (JavaServer Pages) 中&#xff0c;可以使用include特性&#xff0c;include 主要有两种形式&#xff1a;include 指令和 <jsp:include> 动作元素。这两种方式都用于在JSP页面中包含其他资源&#xff0c;但它们的工作方式和应用场景有所不同。 1. include 指令 i…

两个螺旋面的交线

已知轴截面齿形&#xff0c;先得到螺旋面 然后在计算出对应的端面齿形 在用端面齿形来计算和另一个螺旋面的相交曲线。 三维验证这个方法可行&#xff01;

喜大普奔,AI绘画SD3终于开源了,AI绘画又添新利器!【附模型下载和安装包】

sd3终于开源了&#xff01; 没错就是stablediffusion 3.0版本&#xff01;这是stability迄今为止最先进最复杂图像生成模型。 这次开源的是medium版本&#xff0c;总共有三个型号的模型&#xff0c;下面我们来详细的说下sd3的功能特点以及不同型号区别、安装方法&#xff01;…

HTML静态网页成品作业(HTML+CSS)—— 家乡山西介绍网页(3个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有6个页面。 二、作品演示 三、代…

专业设计师推荐的20条用户体验设计黄金准则

在当今的数字世界中&#xff0c;用户体验设计已经成为商业成功的关键因素。它可以实现或摧毁一个产品。今天&#xff0c;我们将讨论该领域的20个基本原则。这些用户体验设计原则不仅被顶级工厂设计师广泛使用&#xff0c;而且为您在设计过程中提供有价值的指导。 1. 以用户为中…

设置生成coredump文件

确保系统已启用核心转储&#xff08;core dump&#xff09;&#xff0c;可以通过设置ulimit命令来配置。可以通过以下命令检查当前的core dump设置&#xff1a; ulimit -c 如果返回值为0&#xff0c;表示core dump功能已经禁用。你可以通过以下命令启用core dump&#xff1a;…

共绘财富与时间画卷,ATFX携手Haofa腕表,开启跨界新篇章

在当前激烈的市场竞争中&#xff0c;品牌创新和多元化、本地化发展已成为企业突破重围&#xff0c;赢得用户和市场份额的关键。作为差价合约行业领军品牌&#xff0c;ATFX勇于突破自我&#xff0c;为探索更多的市场可能性&#xff0c;通过跨界合作、联合营销的策略&#xff0c;…

物联网概念

物联网 物联网简介物联网体系结构物联网体系结构定义物联网体系结构设计原则物联网体系结构四层物联网体系结构感知控制层数据传输层数据处理层应用决策层 物联网关键技术感知标识技术网络与通信技术云计算技术安全技术 已有物联网相关应用架构无线传感器网络的体系结构EPC/UID…

同三维T80005JEHVA 4K视频解码器

同三维T80005JEHVA视频解码器 可解1路4K30HDMI/VGA/CVBS1路3.5音频 可解电台音频网络流&#xff0c;可同时解4个网络流&#xff0c;分割输出 可预设十个流&#xff0c;任意切换1路流输出 <!--[endif]----><!--[if !vml]--> <!--![endif]----> 介绍&…

逆向分析-Ollydbg动态跟踪Ransomware.exe恶意锁机程序

1.认识Ollydbg Ollydbg是一个新的动态追踪工具&#xff0c;将IDA与SoftICE结合起来的思想&#xff0c;Ring 3级调试器&#xff0c;非常容易上手&#xff0c;己代替SoftICE成为当今最为流行的调试解密工具了。同时还支持插件扩展功能&#xff0c;是目前最强大的调试工具。 Oll…