最近项目中用到了webSocket服务,由后台实时向所有的前端推送消息,前端暂时是不可以发消息给后端的,数据的来源是由具体的设备数据收集器收集起来,然后通过socket推送给后端,后端收到数据后,再将这些数据推送给前端。

  听起来业务逻辑有点复杂。其实单独的实现socket或websocket都比较简单,但是二者之间的数据传输问题,困扰了我很久。也想过用redis做一个消息队列,将socket接收到的数据处理后丢进去,然后再用websocket从redis里取出数据,再推送给前端。

  但是。问题来了,这么配置的话,一个简单的功能,要另外再加一个服务出来,配置起来好麻烦的感觉。再说了,目前的业务逻辑是,数据不做任何处理就直接扔出去了,干嘛要一层一层的来设计这些东西呢?虽然它有很好的模式和很高的扩展性,可我就是懒的去写多余的代码来配置这些东西。so,本着能懒就懒的原则,我整出来一套自己适合的方案来做这个事情。

  思路:socket推送给后端的数据是实时的,有则推送,没有就一边呆着,等消息发过来。所以呢,我干嘛不弄个http接口来接收呢,本来数据就不多,老半天才会推一条出来,有时候一天都不会有几条数据,所以,搞一个socket还不如直接提供一个HTTP接口来接收数据来的划算,关键是代码写起来简单啊。所以就有了这个:

@RequestMapping(value = "/socket", method = {RequestMethod.POST, RequestMethod.GET})
public void webSocket(HttpServletRequest request) {
Map map = request.getParameterMap();
...
}

  这个东西没啥可说的,不用测试都知道没问题。

  好了,数据是接收到了,怎么发送给前端呢?我的想法是,把推送前端的代码直接写到上面的代码体里面,这样就能接到一个推送就直接广播给前端,接不到数据就不推送,多好啊。

  想象中的代码应该是这样的:

@RequestMapping(value = "/socket", method = {RequestMethod.POST, RequestMethod.GET})
public void webSocket(HttpServletRequest request) {
Map map = request.getParameterMap();
...
// sendMessageToFront(message);
}

  如果想这样写,要么使用标签注解,要么自定义一个方法,继承websocket来实现功能。but how?

  <坑里的生活就不播了,直接写出坑后的成果吧>

  标签注解的方式或许可以实现,但是,这样以来,就有三个URI提供给前端了,一个用来握手,一个用来发送消息,一个用来接收消息。好吧,前端也以懒为天,能少写一个字母绝不多加半个符号。so,我的这种方案直接被否决了,所以得另寻出路。

  然后就是写个方法继承websocket来实现这个功能了。代码是这样的:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer { @Resource
private AliceWebSocketHandler webSocketHandler; @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler, "/webSocket").setAllowedOrigins("*")
.addInterceptors(new AliceHandShakeInterceptor());
registry.addHandler(webSocketHandler, "/webSockJs").setAllowedOrigins("*")
.addInterceptors(new AliceHandShakeInterceptor()).withSockJS();
}
}
@Component
public class AliceHandShakeInterceptor extends HttpSessionHandshakeInterceptor { @Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
return super.beforeHandshake(request, response, wsHandler, attributes);
} @Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
super.afterHandshake(request, response, wsHandler, exception);
}
}
@Component
public class AliceWebSocketHandler extends TextWebSocketHandler { private static final Logger LOGGER = LoggerFactory.getLogger(AliceWebSocketHandler.class); private static Map<String, WebSocketSession> SESSION_MAP = Maps.newConcurrentMap(); @Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
LOGGER.debug("[{} : {}] has be connected...", session.getUri(), session.getId());
SESSION_MAP.put(session.getId(), session);
} @Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { } @Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
LOGGER.debug("[{} : {}]", session.getUri(), session.getId());
SESSION_MAP.remove(session.getId());
} @Override
public boolean supportsPartialMessages() {
return false;
} /**
* 群发消息
*/
public void broadcast(final TextMessage message) throws IOException {
for (Map.Entry<String, WebSocketSession> entry : SESSION_MAP.entrySet()) {
if (entry.getValue().isOpen()) {
new Thread(() -> {
try {
if (entry.getValue().isOpen()) {
entry.getValue().sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
}

  完事,方法体中,就直接调用broadcast方法就行了,推送消息服务完成。

Spring MVC 实现web Socket向前端实时推送数据的更多相关文章

  1. 使用SignalR ASP.NET Core来简单实现一个后台实时推送数据给Echarts展示图表的功能

    什么是 SignalR ASP.NET Core ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能. 实时 web 功能使服务器端代码可以立 ...

  2. 【原创】node+express+socket搭建一个实时推送应用

    技术背景 Web领域的实时推送技术,也被称作Realtime技术.这种技术要达到的目的是让用户不需要刷新浏览器就可以获得实时更新. 应用场景: 监控系统:后台硬件热插拔.LED.温度.电压发生变化 即 ...

  3. java版Web Socket,实现消息推送

    # web socket是什么? WebSocket协议是基于TCP的一种新的网络协议. 它实现了浏览器与服务器全双工(full-duplex)通信,允许服务器主动发送信息给客户端. ## 用途 实时 ...

  4. Flume连接oracle实时推送数据到kafka

    版本号: RedHat6.5   JDK1.8    flume-1.6.0   kafka_2.11-0.8.2.1 flume安装 RedHat6.5安装单机flume1.6:RedHat6.5安 ...

  5. 服务器端实时推送技术之SseEmitter的用法

    这是SpringMVC提供的一种技术,可以实现服务端向客户端实时推送数据.用法非常简单,只需要在Controller提供一个接口,创建并返回SseEmitter对象,发送数据可以在另一个接口调用其se ...

  6. spring mvc构建WEB应用程序入门例子

    在使用spring mvc 构建web应用程序之前,需要了解spring mvc 的请求过程是怎样的,然后记录下如何搭建一个超简单的spring mvc例子. 1) spring mvc的请求经历 请 ...

  7. 基于Spring MVC的Web应用开发(三) - Resources

    基于Spring MVC的Web应用开发(3) - Resources 上一篇介绍了在基于Spring MVC的Web项目中加入日志,本文介绍Spring MVC如何处理资源文件. 注意到本项目的we ...

  8. [翻译]Spring MVC RESTFul Web Service CRUD 例子

    Spring MVC RESTFul Web Service CRUD 例子 本文主要翻译自:http://memorynotfound.com/spring-mvc-restful-web-serv ...

  9. WEB 实时推送技术的总结

    前言 随着 Web 的发展,用户对于 Web 的实时推送要求也越来越高 ,比如,工业运行监控.Web 在线通讯.即时报价系统.在线游戏等,都需要将后台发生的变化主动地.实时地传送到浏览器端,而不需要用 ...

随机推荐

  1. Robotframework 简介及工作原理

    下面通过官网和网上资料来简单介绍下Robotframework及其工作原理. 官方说明: Robot Framework is a generic test automation framework ...

  2. What Is Your Grade?

    Problem Description “Point, point, life of student!”This is a ballad(歌谣)well known in colleges, and ...

  3. Dalvik虚拟机java方法执行流程和Method结构体分析

    Method结构体是啥? 在Dalvik虚拟机内部,每个Java方法都有一个对应的Method结构体,虚拟机根据此结构体获取方法的所有信息. Method结构体是怎样定义的? 此结构体在不同的andr ...

  4. Lucene原理一

    Lucene 是一个高效的,基于Java 的全文检索库. 所以在了解Lucene之前要费一番工夫了解一下全文检索. 那么什么叫做全文检索呢?这要从我们生活中的数据说起. 我们生活中的数据总体分为两种: ...

  5. Should Assertion Library

    Should Assertion Library,通常在测试时用到,可以与nunit 结合使用. 已经从codeplex 迁移到 github.网址如下 https://github.com/eric ...

  6. [Ubuntu]管理开机启动项的软件

    sudo apt-get install sysv-rc-conf

  7. HLSL-高级着色语言简介【转】

    HLSL-High Level Shader Language 优点 用来书写Vertex Shader和Pixel Shader程序的代码,语法类似于C/C++,在DirectX 8.x的时代,Sh ...

  8. SqlServer Session共享注意点

    公司下派任务,之前的网站是一台服务器,由于用户过多,负载过大,现在老大要求多加一台服务器.加就加贝,应该跟我这DEV没有 关系吧,应该不会碰到Source的吧.但是,之前网站有一些数据是放在Sessi ...

  9. char、varchar、nchar、nvarchar特点比较

    于程序中的string型字段,SQLServer中有char.varchar.nchar.nvarchar四种类型来对应(暂时不考虑text和ntext),开建立数据库中,对这四种类型往往比较模糊,这 ...

  10. .net core获取服务器本地IP及Request访问端口

    string str = (Request.HttpContext.Connection.LocalIpAddress.MapToIPv4().ToString() + ":" + ...