Java版WebSocket消息推送系统搭建

最近在做消息推送,网上查了一些资料,开始想的是用MQ来做,后面发现用WebSocket来做的话感觉应该要简单点,话不多说,准备撸代码。


后端核心代码



/*** 监听器类:主要任务是用ServletRequest将我们的HttpSession携带过去* @author Monkey* @date 2020-05-23*/
@Component
public class RequestListener implements ServletRequestListener {@Overridepublic void requestInitialized(ServletRequestEvent sre) {//将所有request请求都携带上httpSessionHttpSession httpSession= ((HttpServletRequest) sre.getServletRequest()).getSession();String uid = sre.getServletRequest().getParameter("uid");if (!StringUtils.isEmpty(uid)) {httpSession.setAttribute("uid", uid);SysContent.setUserLocal(uid);}}
/*** Type: WebSocketConfig* Description: WebSocket配置类* @author Monkey* @date 2020-05-23*/
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

/*** Type: WebSocketServer* Description: WebSocketServer,实现服务器客户端平等交流,达到服务器可以主动向客户端发送消息** @author Monkey* @date 2020-05-23*/
@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {//日志记录器private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);//高效,弱一致性,放的是WebSocketServer而非session是为了复用自身的方法private static transient volatile Set<WebSocketServer> webSocketSet = ConcurrentHashMap.newKeySet();private static transient volatile Set<WebSocketServer> tempWebSocketSet = ConcurrentHashMap.newKeySet();//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;private static transient ConcurrentHashMap<String, Session> map = new ConcurrentHashMap();/*** Title: sendInfo* Description: 群发消息* @param message*/public static void sendInfo(String message, String sid) throws IOException {LOGGER.info("webSocket-sendInfo群发消息:" + message);RecordLogUtil.info("在线人数:" + getOnlineCount());if (!StringUtils.isEmpty(sid)) {Set<Map.Entry<String, Session>> entries = map.entrySet();for(Map.Entry<String, Session> m : entries){if (m.getKey().equals(sid)) {Session s2 = m.getValue();webSocketSet.forEach(ws -> {if (ws.session.getId() == s2.getId()) {ws.sendMessage(message);return;}});map.remove(m);break;}}} else {tempWebSocketSet = ConcurrentHashMap.newKeySet();for (Map.Entry<String, Session> m : map.entrySet()) {Session s2 = m.getValue();webSocketSet.forEach(ws -> {if (ws.session.getId() == s2.getId()) {ws.sendMessage(message);tempWebSocketSet.add(ws);return;}});}//过滤完已经挂断的sessionwebSocketSet = tempWebSocketSet;}}/*** Title: getOnlineCount* Description: 获取连接数* @return*/public static int getOnlineCount() {return map.size();}/* *********************以下为非static方法************************** *//*** Title: sendMessage* Description: 向客户端发送消息* @param message* @throws IOException*/public boolean sendMessage(String message) {try {this.session.getBasicRemote().sendText(message);return true;} catch (IOException error) {LOGGER.error("webSocket-sendMessage发生错误:" + error.getClass() + error.getMessage());return false;}}/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session) throws IOException {String uid = SysContent.getUserLocal();RecordLogUtil.info("uid=" + uid);this.session = session;if (StringUtils.isEmpty(uid)){sendMessage("连接失败");session.close();return;} else {map.put(uid, this.session);webSocketSet.add(this);     //加入set中sendMessage("连接成功-" + uid);RecordLogUtil.info("当前在线人数: " + getOnlineCount());}}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {webSocketSet.remove(this);  //从set中删除//这里要删除map里面对象for(Map.Entry<String, Session> m : map.entrySet()){if (m.getValue() == this.session) {map.remove(m);RecordLogUtil.info("用户" + m.getKey() + "已关闭连接!");break;}}RecordLogUtil.info("在线人数:" + getOnlineCount() + ", 关联在线人数:" + map.size());}/*** 收到客户端消息后调用的方法* @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session session) {LOGGER.info("来自客户端(" + session.getId() + ")的消息:" + message);sendMessage("Hello, nice to hear you! There are " + webSocketSet.size() + " users like you in total here!");}/*** Title: onError* Description: 发生错误时候回调函数* @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {LOGGER.error("webSocket发生错误:" + error.getClass() + error.getMessage());}@Overridepublic int hashCode() {return super.hashCode();}@Overridepublic boolean equals(Object obj) {return super.equals(obj);}
}

/*** 监听器类:主要任务是用ServletRequest将我们的HttpSession携带过去* @author Monkey* @date 2020-05-23*/
public class SysContent {private static ThreadLocal<HttpServletRequest> requestLocal = new ThreadLocal<HttpServletRequest>();private static ThreadLocal<HttpServletResponse> responseLocal = new ThreadLocal<HttpServletResponse>();private static ThreadLocal<String> userLocal = new ThreadLocal<String>();public static String getUserLocal() {return userLocal.get();}public static void setUserLocal(String userLocal) {SysContent.userLocal.set(userLocal);}public static HttpServletRequest getRequest() {return (HttpServletRequest) requestLocal.get();}public static void setRequest(HttpServletRequest request) {requestLocal.set(request);}public static HttpServletResponse getResponse() {return (HttpServletResponse) responseLocal.get();}public static void setResponse(HttpServletResponse response) {responseLocal.set(response);}public static HttpSession getSession() {return (HttpSession) ((HttpServletRequest) requestLocal.get()).getSession();}
}

前端代码


<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><title>WebSocket测试</title><meta charset="utf-8"><script src="/socket/js/jquery-3.3.1.min.js"></script><script src="/socket/js/sockjs.min.js"></script>
</head>
<body>
<!-----start-main---->
<div class="main"><h2>socketTest</h2><input type="button" id="send" value="点击向服务器发送消息"><p id="recive"></p></div>
<!-----//end-main---->
</body>
<script type="text/javascript">var ws = null;var ws_status = false;function openWebSocket(){//这里为了模拟不同的模拟器。sid是随机数,开多个浏览器窗口的话,就用随机值测试连接var sid = Math.random()*10000;//如果是正式使用,则这个就是绑定用户的唯一值,一般为id固定值//sid = 1;console.log("sid=" + sid);//判断当前浏览器是否支持WebSocketif ('WebSocket' in window) {console.log("window...");ws = new WebSocket("ws://"+window.location.host+"/websocket?uid=" + sid);} else if ('MozWebSocket' in window) {console.log("MozWebSocket...");websocket = new MozWebSocket("ws://"+window.location.host+"/websocket?uid=" + sid);} else {console.log("SockJS...");ws = new SockJS("http://"+window.location.host+"/websocket?uid=" + sid);}//这个事件是接受后端传过来的数据ws.onmessage = function (event) {//根据业务逻辑解析数据console.log("Server:");console.log(event);};ws.onclose = function (event) {console.log("Connection closed!");ws_status = false;};ws.onopen = function (event){ws_status = true;console.log("Connected!");};ws.onerror = function (event){console.log("Connect error!");};}//如果连接失败,每隔两秒尝试重新连接setInterval(function(){if(!ws_status){openWebSocket();}}, 2000);$("#send").click(function(){ws.send("Hello, server, I am browser.");$.ajax({url: "/test/send",data: {uid: null},type: "get",dataType: "json",success: function(data) {// data = jQuery.parseJSON(data);  //dataType指明了返回数据为json类型,故不需要再反序列化console.log("开始发送广播啦!")}});});
</script>
</html>

前端示意图



demo 测试代码已经上传到csdn,喜欢的话可以前往下载。

https://download.csdn.net/download/lj88811498/12453985

Java版WebSocket消息推送系统搭建相关推荐

  1. Netty-SocketIO:最好用的Java版即时消息推送

    Netty-SocketIO是一个开源的.基于Netty的.Java版的即时消息推送项目.通过Netty-SocketIO,我们可以轻松的实现服务端主动向客户端推送消息的场景,比如说股票价格变化.K线 ...

  2. java socket 推送机制_Java中websocket消息推送的实现代码

    一.服务层 package com.demo.websocket; import java.io.IOException; import java.util.Iterator; import java ...

  3. 如何利用springboot快速搭建一个消息推送系统

    最近在完善毕设的路上,由于是设计一个远程控制物联网系统,所以服务端到硬件我选用了MQTT协议.因为MQTT的发布/订阅模式很适合这种场景.接下来就来聊聊遇到的一些问题以及解决思路吧. 毕设技术栈:sp ...

  4. java/web/springboot项目使用WebSocket消息推送

    java/web/springboot项目使用WebSocket消息推送 最近项目中,有消息推送的广播和在线咨询的功能,以前也没搞过啊,有些小伙伴估计也是,那肯定要赶紧学习起来啊~ 不说废话,今天就告 ...

  5. 开源实时消息推送系统 MPush

    系统介绍 mpush,是一款开源的实时消息推送系统,采用java语言开发,服务端采用模块化设计,具有协议简洁,传输安全,接口流畅,实时高效,扩展性强,可配置化,部署方便,监控完善等特点.同时也是少有的 ...

  6. node.js Websocket消息推送---GoEasy

    Goeasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送!个人感觉goeasy推送更稳定,推送速度快,代码简单易懂上手快 浏览器兼容性:GoEasy推送支持websocket 和 ...

  7. SpringBoot2.x 整合websocket 消息推送,单独发送信息,群发信息

    根据公司需求在SpringBoot项目中集成站内信,于是,我做了一个SpringBoot2.x 整合websocket 消息推送,给指定用户发送信息和群发信息即点点对方式和广播方式2种模式. 文章目录 ...

  8. go语言消息推送服务器,Golang 消息推送系统

    ## Golang 消息推送系统 - 使用 websocket 协议,实现全局推送,和分房间推送,实现用户加入房间,退出房间 - gateway 长连接网关服务器,管理全部的链接,以及房间等相关操作 ...

  9. 【Java集成小米消息推送(海外版)】

    Java集成小米消息推送(海外版) 注册登录: 小米推送运营中心 提交需要的信息,一般为包名等信息(或直接让Android开发提交) 需要的配置信息 1.App Secret 2.Package na ...

最新文章

  1. c语言 在线oj系统,开源的在线评测系统——Vakuum
  2. MySQL 高级 游标基本操作
  3. 第19次csp认证 202006-2 稀疏向量(C++)
  4. 2021年00后生活方式洞察报告
  5. 计算机组成原理与汇编语言程序设计课后答案,计算机组成原理与汇编语言程序设计课后习题及解答(详解)...
  6. Spring4.3.10 集成 Apache CXF 3.3 详细说明
  7. java工程师linux命令大全
  8. 中国新材料产业十四五竞争格局及产销趋势研究报告2021年版
  9. [Objective-C]第一天
  10. 支付宝异步回调步骤+内网穿透++雷神商城项目
  11. GTD时间管理,如何收集?| 每天成就更大成功
  12. HTML5创建热点区域
  13. 二分法、三分法 --算法竞赛专题解析(1)
  14. 数据库分库分表解决方案
  15. 【后端教程】深入浅出动态化 SSR 服务(一):开发工具篇
  16. ismusicactive副作用_Android得到一个闹钟在第三方
  17. Las Vegas 与回溯组合法解八皇后问题
  18. 免费在线基本电气图 + 示例
  19. html可暂停倒计时代码,js实现倒计时器自定义时间和暂停
  20. 人工智能技术,能够为“心理疫情”做些什么

热门文章

  1. 海思Hi3559a音视频同时播放的例子
  2. Echarts配置项-2
  3. Matlab电路原理应用——计算未知电阻
  4. python处理Excel列中的图片url地址批量下载至本地
  5. 利用百度指数和热词排行榜提升网站流量
  6. 计算机毕业设计Java校园便利店信息系统开发(源码+系统+mysql数据库+Lw文档)
  7. DAS、NAS和SAN,IPSAN的基本了解
  8. php超大数组插入数据库处理
  9. 换发型软件有哪些?试试这些软件吧
  10. 6、RH850 F1 AD转换功能和配置