最近项目中用到了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. nodejs+express安装配置(Linux版本)

    在ubuntu下面,直接从源里面安装nodejs的话,此版本还行,但是相关的express等,会比较老. 采用源码安装,先下载nodejs的源码,然后三步: ./configure make make ...

  2. Sql 辅助

    1.清空数据表 SELECT 'TRUNCATE TABLE '+name AS TruncateSql FROM sys.tables

  3. Backbone学习笔记 - Collection及Router篇

    Collection Collection可以看成是Model的集合.以下是一个集合的例子: var Song = Backbone.Model.extend({ defaults: { name: ...

  4. 【转】SQL FOR XML简介及用法

    摘要:sql中的for xml语法为表转化为xml提供了很好的支持,当然使用同样的程序语言也能够达到同样的效果,但是有了for xml将使得这一切更加的方便. 主要内容: Select 的查询结果会作 ...

  5. MPLS 网络中的 MTU

    MPLS MTU的大小可以设置为64-65535之间,在MPLS网络中,标签的大小是计入到MTU中的,所以在MPLS网络MTU是一个常见的问题.     在Ethernet接口上,一般数据最长为150 ...

  6. Mac OS 10.12 - 安装JAVA!

    一,下载JDK: 下载地址:版本1.8.0 http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f07 ...

  7. 二,PHP会话机制---session的基本使用

    1,思考:登录网站后,在每个网页都能拿到用户信息 (1) 使用超链接传递用户名,这样太繁琐了,不建议使用 . (2) 使用数据库,每打开一个页面都查询一次用户信息表,这样网页加载速度变慢,用户体验变差 ...

  8. 二,windows下安装memcached服务

    window下安装memcached服务的流程如下: 1. 下载memcache的windows稳定版,解压放某个盘下面,比如在c:\memcached 2. 在终端(也即cmd命令界面)下输入 ‘c ...

  9. SVN版本服务器的搭建和远程控制

    版本服务器是用SVN server(这个东西是放到版本机服务器上的)  版本管理工具是用小乌龟(tortoiseSVN,这个是在各个机器上使用) 1,昨天下载了SVN server 按照网上教程搭建好 ...

  10. 学习Python中的集合

    创建集合 使用工厂方法 set()和 frozenset(): >>> s = set('cheeseshop') >>> s set(['c', 'e', 'h' ...