业务背景:app端需要实时接收到服务端的交易价格信息,肯定无法实时主动去轮询拉取pull操作,需要一种push实时数据到app端,因此websocket技术正好应用于此。

技术栈选型:

1 传统型 使用@ServerEndpoint注解实现

2 前沿性 使用springboot 三个核心 一配二拦三监听

一配指的 是注册并配置websocket的handler监听器和拦截器

二拦指的 是拦截客户端请求的websocket的参数和权鉴服务

三监听指的 是监听各种事件(请求连接/接收消息/关闭连接)

为什么要用springboot集成的websocket,主要是因为springboot对websocket做了很好的支持,而且提供了在建立连接前可以权鉴和做一些其他的事情。

代码实现:

maven 主要依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

一 配置服务

/*** 注册websocket服务* @author panmeng*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new EpaiWebSocketHandler(),"/websocket").setAllowedOrigins("*").addInterceptors(new HandShakeInterceptor());}
}

二 拦截器 (可以接收url的数据)

@Slf4j
public class HandShakeInterceptor extends HttpSessionHandshakeInterceptor {/*** 在WebSocket连接建立之前的操作,以鉴权为例* @param request* @param response* @param wsHandler* @param attributes* @return* @throws Exception*/@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {log.info("Handle before webSocket connected. ");// 获取url传递的参数,通过attributes在Interceptor处理结束后传递给WebSocketHandler// WebSocketHandler可以通过WebSocketSession的getAttributes()方法获取参数ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;String catId = serverRequest.getServletRequest().getParameter("object_id");if (TokenValidation.validateSign()) {log.info("Validation passed. WebSocket connecting.... ");attributes.put("catId", catId);return super.beforeHandshake(request, response, wsHandler, attributes);} else {log.error("Validation failed. WebSocket will not connect. ");return false;}}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,WebSocketHandler wsHandler, Exception ex) {// 省略}
}

三 监听 并处理

主要代码实现是通过一个商品的id作为key,然后每一个查看当前商品的用户都会给他建立一个websession会话连接,记录下来,然后当服务端有最新的交易数据过来时,调用当前的sendWebsocketMessage dubbo接口即可实现将最新的交易消息发送到各个连接客户端。

/*** @author panmeng*/
@Slf4j
@Service("websocketService")
public class EpaiWebSocketHandler implements WebSocketHandler, WebsocketService {private static ConcurrentMap<String,List<WebSocketSession>> existSocketClientMap = new ConcurrentHashMap<>();/*** 当前在线数*/private static int onlineCount = 0;@Overridepublic void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {log.info("success connect the web socket server...the remote sessionId is {}",webSocketSession.getId());Map<String, Object> attributes = webSocketSession.getAttributes();Object catAucId = attributes.get("catId");if(catAucId!=null&& !StringUtils.isEmpty(catAucId.toString())){List<WebSocketSession> historySessionList= existSocketClientMap.get(catAucId.toString());List<WebSocketSession> sessionList=new ArrayList<>();sessionList.add(webSocketSession);if(!CollectionUtils.isEmpty(historySessionList)){sessionList.addAll(historySessionList);}existSocketClientMap.put(catAucId.toString(),sessionList);}else{throw new BusinessException(GlobalConstant.CAT_AUC_ID_PARAM_NOT_NULL);}addOnlineCount();log.info("current connect total count is :{}",onlineCount);}private static synchronized void addOnlineCount() {EpaiWebSocketHandler.onlineCount++;}@Overridepublic void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {String msg = webSocketMessage.getPayload().toString();log.info("the web socket receive client message,info is {} prepare start send...",msg);BaseMessageInfo baseMessageInfo = JSONObject.parseObject(msg, BaseMessageInfo.class);Integer catId=null;if(baseMessageInfo.getData() !=null){JSONObject data= (JSONObject) baseMessageInfo.getData();if(data !=null &&  data.get("catId") !=null){catId= Ints.tryParse(data.get("catId").toString());}}if(catId ==null){throw new BusinessException(GlobalConstant.CAT_INFO_NOT_FIND_ERROR);}log.info("the web socket receive client message,catId is {}",catId);List<WebSocketSession> historySessionList= existSocketClientMap.get(catId.toString());if(!CollectionUtils.isEmpty(historySessionList)){log.info("the web socket should send client count is {}",historySessionList.size());historySessionList.stream().forEach(session->{try {if(session.isOpen()){session.sendMessage(new TextMessage(msg));}else{log.info("the session {} is already closed,now should remove this session from history memory",session);afterConnectionClosed(session,CloseStatus.NORMAL);}} catch (IOException e) {log.error("the sessionId {} an error occurred while sending the message...",session.getId());e.printStackTrace();} catch (Exception e) {log.error("the sessionId {} an error occurred while the session closed...",session.getId());e.printStackTrace();}});}log.info("the web socket receive clint message,info is {} send to all complete...",msg);}@Overridepublic void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {log.info("the connection happen unknow error,the remote address is {}",webSocketSession.getRemoteAddress());if (webSocketSession.isOpen()) {webSocketSession.close();}}@Overridepublic void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {log.info("the connection will close,sessionId is:{}",webSocketSession.getId());if (webSocketSession.isOpen()) {webSocketSession.close();}Iterator<Map.Entry<String, List<WebSocketSession>>> iterator = existSocketClientMap.entrySet().iterator();while (iterator.hasNext()){Map.Entry<String, List<WebSocketSession>> entry = iterator.next();List<WebSocketSession> sessionList = entry.getValue();if(sessionList.contains(webSocketSession)){sessionList.remove(webSocketSession);}}log.info("the connection already closed,sessionId is:{}",webSocketSession.getId());}@Overridepublic boolean supportsPartialMessages() {return false;}@Overridepublic ReturnJson sendWebsocketMessage(String msg) {log.info("the web socket receive clint message,info is {}",msg);BaseMessageInfo baseMessageInfo = JSONObject.parseObject(msg, BaseMessageInfo.class);Integer catId=null;if(baseMessageInfo.getData() !=null){JSONObject data= (JSONObject) baseMessageInfo.getData();if(data !=null &&  data.get("catId") !=null){catId= Ints.tryParse(data.get("catId").toString());}}if(catId ==null){throw new BusinessException(GlobalConstant.CAT_INFO_NOT_FIND_ERROR);}log.info("the web socket receive clint message,catId is {}",catId);List<WebSocketSession> historySessionList= existSocketClientMap.get(catId.toString());if(!CollectionUtils.isEmpty(historySessionList)){historySessionList.stream().forEach(session->{try {if(session.isOpen()){session.sendMessage(new TextMessage(msg));}else{log.info("the session {} is already closed,now should remove this session from history memory",session);afterConnectionClosed(session,CloseStatus.NORMAL);}} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}});}log.info("the web socket receive clint message,info is {} send to all complete...",msg);return ReturnJson.success();}
}

Springboot版本的WebSocket向app端推送消息实现相关推荐

  1. springboot 实现服务端推送消息

    文章目录 前言 一.关于SSE 1. 概念介绍 2. 特点分析 3. 应用场景 二.SpringBoot实现 三.前端vue调用 四.一些问题 前言 服务端推送消息我们采用SSE方式进行推送. 一.关 ...

  2. ios极光推送 App收到推送消息时,修改BadgeNumber,同时点击状态栏消息以后跳到指定的页面和静默推送

    极光推送生产环境测试需要打包为adhot或者用testflight 在收到远程推送的消息的时候,有以下三种情况需要考虑: 1. 程序在后台运行 2. 程序未运行 3. 程序运行在前台 原则上,应用在收 ...

  3. nett服务器接收消息的方法,C#(一沙框架) .net core3.1 SignalR 服务端推送消息至客户端的实现方法,用弹窗插件进行显示,非常美观实用...

    C#(一沙框架) .net core3.1 SignalR 服务端推送消息至客户端的实现方法,用弹窗插件进行显示,非常美观实用 运行效果: 1.安装Microsoft.AspNetCore.Signa ...

  4. 个推PC端推送消息至App

    本文以个推透传消息为例: 个推SDK下载地址:点击打开链接 开发准备见官方文档:http://docs.igetui.com/pages/viewpage.action?pageId=590077 类 ...

  5. Java 服务端推送消息有那么难吗?

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 转自公众号:码农小胖哥 今天项目经理交给我一个开发任务.如果有人在前台下了订单就给后台仓库管 ...

  6. websocket给指定客户端推送消息

    业务场景 最近有一个业务场景是要做实时语音转义,考虑到实时性,所以决定采用websocket实现. 业务场景是A客户端(手机)进行语音转义的结果实时同步到B客户端(pc),这就需要用到websocke ...

  7. Android端推送消息之极光推送

    推送方式 轮询 --实现方式: 周期性主动获取网络中的数据; --缺点: 费电, 费流量; SMS --实现方式: 服务器端向手机端发送短信, 手机监听短信广播, 将拦截的短信信息进行显示; --优点 ...

  8. WebSocket + SpringBoot + VUE实现后端实时向前端推送消息

    一.目的 众所周知,正常来说在前后端通信中,后端往往处于一个被动的状态,对前端的请求作出对应的响应.但有的时候我们会遇到需要后端前前端推送数据的需求,比如消息.邮件等的推送.这个时候,实现的一种方式是 ...

  9. server端推送消息机制

    推送技术相关请参加WIKI: https://zh.wikipedia.org/wiki/%E6%8E%A8%E9%80%81%E6%8A%80%E6%9C%AF 场景: 监控系统:后台硬件温度.电压 ...

  10. springboot 之 webscoket 服务端推送

    因为最近有后端实时推送数据的需求,所以想到了websocket组件,在此写一下springboot集成使用websocket的方法,供各位童鞋参考. 注:基于test项目. 1.首先打开pom.xml ...

最新文章

  1. Angular中使用双向数据绑定操作表单的input、checkboc、radio、select、textarea实现简单的人员登记系统实例
  2. Go 从入门到精通(三)字符串,时间,流程控制,函数
  3. 家用笔记本电脑什么牌子好_家用什么牌子的吸尘器好?
  4. Android对话框dialog大全(代码直接可用)
  5. 第九十七期:新版Kite:实时补全代码,Python之父都发声力挺!
  6. css3弧形跑道效果_Css 实现漂亮弧形
  7. 【今日CV 计算机视觉论文速览 第131期】Mon, 17 Jun 2019
  8. RedisTemplate设置过期时间
  9. ios微内核和鸿蒙微内核,华为发布基于微内核、面向全场景的分布式操作系统:鸿蒙OS...
  10. supersu二进制更新安装失败_Q音直播编译优化与二进制集成方案
  11. 【数学基础】机器学习中的几个熵
  12. 打开*.gd文件的方法
  13. pyhive 安装测试及问题解决
  14. Error: Cannot find module ‘webpack‘
  15. Centos7 搭建多用户SFTP服务,并开启日志记录
  16. W806做电机转速调控
  17. 极致体验,解密微信背后的音视频通话技术
  18. 用JS实现贪吃蛇小游戏
  19. A Game of Thrones(15)
  20. java 导出压缩文件,里面文件名字乱码的问题(麒麟系统,linux)

热门文章

  1. Mac 安装非信任开发者软件
  2. questasim编译报error: Declarations must precede statements. Look for stray semicolons.
  3. Excel中不复制隐藏行
  4. Android触摸屏校对,android实现触摸屏校准
  5. Word2010邮件合并(附带照片)
  6. Xcode常用快捷键
  7. python乌龟吃鱼
  8. 按需使用vue-cli-plugin-element插件
  9. python unpack函数_python的struct.unpack函数
  10. 高中计算机上册知识总结怎么写,高中计算机总结范文