最近项目中用到了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. 团队项目第六周——Alpha阶段项目复审

    排名 队名 项目名 优点 缺点 1 大猪蹄子队 四六级背单词游戏 功能开发出来了,界面简洁美观. 功能的确开发出来了,但是还未完成整个程序.不过考虑到开发时长问题,可以理解.页面还是比较简洁,但是测试 ...

  2. Difference between the Bill of distribution and sourcing rule.

        https://forums.oracle.com/thread/936768 This is from a users guide  Oracle Supply Chain Planning ...

  3. 射线与平面的相交检测(Ray-Plane intersection test)【转】

    射线的定义 在欧几里德几何中,射线的定义是:直线上一点和它一旁的部分.由此可知,射线有两个性质,一是只有一个端点,二是一端无限延伸. 射线的参数方程 其中p0是射线的起点, u是射线的方向向量,t & ...

  4. 设计模式之迭代器模式(Iterator Pattern)

    一.什么是迭代器模式? 用迭代器来封装集合对象的遍历细节,使调用者能够通过统一的接口来实现对集合的遍历 迭代器也给集合对象提供了一定的保护,想要遍历集合,直接调用迭代器的方法就好了,我们不知道也不必知 ...

  5. DateTimeField如何自动设置为当前时间并且能被修改 ——django日期时间字段的使用

    参考于:https://www.cnblogs.com/huchong/p/7895263.html 创建django的model时,有DateTimeField.DateField和TimeFiel ...

  6. win10 下Oracle安装

    在win10 64bit下安装oracle 11的时候,有些问题不注意,安装的时候才遇到就gg了.下面将介绍win10下安装oracle 11的步骤以及安装过程中遇到的一些问题及解决方案. 安装过程中 ...

  7. Navicat 12破解工具 +安装包

    下载地址: https://www.lanzous.com/b657322/ 密码:1j9x zip解压密码:gubin 下载完成 是这样的  先安装第一个  安装完成后 不要打开 ,把第二个复制到安 ...

  8. js代码上的优化

    例1  if ( config.url === '/web/teacher/classes'  || config.url === '/web/teacher/students || config.u ...

  9. 看linux正在运行的服务用哪个命令?

    https://zhidao.baidu.com/question/117779006.html 查看服务进程:ps aux查看服务cpu利用:top查看服务对应端口:netstat -nlp pst ...

  10. IntelliJ IDEA优秀插件(编程通用)

    一.IntelliJ IDEA开发 最近大部分开发IDE工具都切换到了,所以也花了点心思去找了相关的插件.这里整理的适合各种语言开发的通用插件,也排除掉IntelliJ IDEA自带的常用插件了(有些 ...