使用spring boot +WebSocket实现(后台主动)消息推送 (一)

转载 2018年04月16日 15:36:02

最近有一个优化需求,将浏览器轮询获取后台消息改成实时获取并且不轮询,轮询太膈应了。

然后我就找各种资料,一开始同事推荐dwz,后来发现不太适用于目前的项目(也许能实现只是我不知道如何实现)。

后来了解到WebSocket,网上看了很多文档都是类似聊天室的场景,并不适用。在此,我主要介绍下 服务器主动推送,由服务端来触发而不是浏览器端发起。

WebSocket 主要能实现的场景:

1、网页聊天室

2、服务器消息实时通知

WebSocket 使用方法应该有很多,在次介绍下使用  spring boot(集成了tomcat8)+h5 环境下的实现。

话不多说,直接上代码,想深入了解WebSocket 的请查阅相关介绍。

1.pom

[html] view plain copy
  1. <dependency>  
  2.            <groupId>org.springframework.boot</groupId>  
  3.            <artifactId>spring-boot-starter-websocket</artifactId>  
  4.        </dependency>  
2.使用@ServerEndpoint创立websocket endpoint

[java] view plain copy
  1. @Configuration  
  2. public class WebSocketConfig {  
  3.     @Bean  
  4.     public ServerEndpointExporter serverEndpointExporter() {  
  5.         return new ServerEndpointExporter();  
  6.     }  
  7.   
  8. }  
3.具体实现类可自己选择url要不要带参数
[java] view plain copy
  1. package com.star.manager.service;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.concurrent.CopyOnWriteArraySet;  
  5.   
  6. import javax.websocket.OnClose;  
  7. import javax.websocket.OnError;  
  8. import javax.websocket.OnMessage;  
  9. import javax.websocket.OnOpen;  
  10. import javax.websocket.Session;  
  11. import javax.websocket.server.ServerEndpoint;  
  12.   
  13. import lombok.extern.slf4j.Slf4j;  
  14.   
  15. import org.springframework.stereotype.Component;  
  16. @Slf4j  
  17. //@ServerEndpoint("/websocket/{user}")  
  18. @ServerEndpoint(value = "/websocket")  
  19. <strong>@Component</strong>  
  20. public class WebSocketServer {  
  21.     //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。  
  22.     private static int onlineCount = 0;  
  23.     //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。  
  24.    <strong> </strong>private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();  
  25.   
  26.     //与某个客户端的连接会话,需要通过它来给客户端发送数据  
  27.     private Session session;  
  28.   
  29.     /** 
  30.      * 连接建立成功调用的方法*/  
  31.     @OnOpen  
  32.     public void onOpen(Session session) {  
  33.         this.session = session;  
  34.         webSocketSet.add(this);     //加入set中  
  35.         addOnlineCount();           //在线数加1  
  36.         log.info("有新连接加入!当前在线人数为" + getOnlineCount());  
  37.         try {  
  38.              sendMessage("连接成功");  
  39.         } catch (IOException e) {  
  40.             log.error("websocket IO异常");  
  41.         }  
  42.     }  
  43.     //  //连接打开时执行  
  44.     //  @OnOpen  
  45.     //  public void onOpen(@PathParam("user") String user, Session session) {  
  46.     //      currentUser = user;  
  47.     //      System.out.println("Connected ... " + session.getId());  
  48.     //  }  
  49.   
  50.     /** 
  51.      * 连接关闭调用的方法 
  52.      */  
  53.     @OnClose  
  54.     public void onClose() {  
  55.         webSocketSet.remove(this);  //从set中删除  
  56.         subOnlineCount();           //在线数减1  
  57.         log.info("有一连接关闭!当前在线人数为" + getOnlineCount());  
  58.     }  
  59.   
  60.     /** 
  61.      * 收到客户端消息后调用的方法 
  62.      * 
  63.      * @param message 客户端发送过来的消息*/  
  64.     @OnMessage  
  65.     public void onMessage(String message, Session session) {  
  66.         log.info("来自客户端的消息:" + message);  
  67.   
  68.         //群发消息  
  69.         for (WebSocketServer item : webSocketSet) {  
  70.             try {  
  71.                 item.sendMessage(message);  
  72.             } catch (IOException e) {  
  73.                 e.printStackTrace();  
  74.             }  
  75.         }  
  76.     }  
  77.   
  78.     /** 
  79.      *  
  80.      * @param session 
  81.      * @param error 
  82.      */  
  83.     @OnError  
  84.     public void onError(Session session, Throwable error) {  
  85.         log.error("发生错误");  
  86.         error.printStackTrace();  
  87.     }  
  88.   
  89.   
  90. <strong>    public void sendMessage(String message) throws IOException {  
  91.         this.session.getBasicRemote().sendText(message);  
  92.     }</strong><strong>  
  93.   
  94.   
  95.     /** 
  96.      * 群发自定义消息 
  97.      * */  
  98.     public static void sendInfo(String message) throws IOException {  
  99.         log.info(message);  
  100.         for (WebSocketServer item : webSocketSet) {  
  101.             try {  
  102.                 item.sendMessage(message);  
  103.             } catch (IOException e) {  
  104.                 continue;  
  105.             }  
  106.         }  
  107.     }</strong>  
  108.   
  109.     public static synchronized int getOnlineCount() {  
  110.         return onlineCount;  
  111.     }  
  112.   
  113.     public static synchronized void addOnlineCount() {  
  114.         WebSocketServer.onlineCount++;  
  115.     }  
  116.   
  117.     public static synchronized void subOnlineCount() {  
  118.         WebSocketServer.onlineCount--;  
  119.     }  
  120. }  

后台触发有多种,controller,定时任务,mq等,这贴一个controller代码

[java] view plain copy
  1. @RequestMapping(value="/pushVideoListToWeb",method=RequestMethod.POST,consumes = "application/json")  
  2. public @ResponseBody Map<String,Object> pushVideoListToWeb(@RequestBody Map<String,Object> param) {  
  3.  Map<String,Object> result =new HashMap<String,Object>();  
  4.    
  5.  try {  
  6.      WebSocketServer.sendInfo("有新客户呼入,sltAccountId:"+CommonUtils.getValue(param, "sltAccountId"));  
  7.      result.put("operationResult"true);  
  8.  }catch (IOException e) {  
  9.      result.put("operationResult"true);  
  10.  }  
  11.  return result;  
  12. }  


重要的地方我都加粗了,主要是这段,使用这个方法,可以实现服务器主动推送。

[java] view plain copy
  1. public void sendMessage(String message) throws IOException {  
  2.     this.session.getBasicRemote().sendText(message);  
  3. }  
简单说说:

当有新连接进来,记录在静态成员变量webSocketSet里面,相当于一个缓存。后台服务调用sendMessage或sendInfo方法,即可向已登录的客户端推送消息。

4.js(html就不写了,谁边找个能触发这个js的就可以)

[javascript] view plain copy
  1. socket = new WebSocket("ws://localhost:9094/starManager/websocket/张三");  
  2.         var socket;  
  3.         if(typeof(WebSocket) == "undefined") {  
  4.             console.log("您的浏览器不支持WebSocket");  
  5.         }else{  
  6.             console.log("您的浏览器支持WebSocket");  
  7.               
  8.             //实现化WebSocket对象,指定要连接的服务器地址与端口  
  9.             //socket = new WebSocket("ws://localhost:9094/starManager/websocket/张三");  
  10.             socket = new WebSocket("ws://localhost:9094/starManager/websocket");  
  11.             //打开事件  
  12.             socket.onopen = function() {  
  13.                 console.log("Socket 已打开");  
  14.                 //socket.send("这是来自客户端的消息" + location.href + new Date());  
  15.             };  
  16.             //获得消息事件  
  17.             socket.onmessage = function(msg) {  
  18.                 console.log(msg.data);  
  19.                 //发现消息进入    调后台获取  
  20.                 getCallingList();  
  21.             };  
  22.             //关闭事件  
  23.             socket.onclose = function() {  
  24.                 console.log("Socket已关闭");  
  25.             };  
  26.             //发生了错误事件  
  27.             socket.onerror = function() {  
  28.                 alert("Socket发生了错误");  
  29.             }  
  30.              $(window).unload(function(){  
  31.                   socket.close();  
  32.                 });  
  33.   
  34. //                                  $("#btnSend").click(function() {  
  35. //                                      socket.send("这是来自客户端的消息" + location.href + new Date());  
  36. //                                  });  
  37. //  
  38. //                                  $("#btnClose").click(function() {  
  39. //                                      socket.close();  
  40. //                                  });  
  41.         }  
  42.                                   
代码就这么多,我的用这些代码就跑的起来。做的时候出现过页面报404等错误,如果也是spring boot+h5,仔细核对下和我代码有无区别,加配置 路径是有ok,问题应该不大。


如果你恰好也有可以用WebSocket实现的类似场景,希望对你有帮助。我实现的这个功能,当然也是网上看资料学习的,得到很多同行的帮助,在次只是整理下,突出主动推送也能实现(之前认为这个只能实现聊天室),再次感谢帮助过我的

同行们,祝你们在写bug路上,越走越远。。。


使用spring boot +WebSocket实现(后台主动)消息推送

有个需求:APP用户产生某个操作,需要让后台管理系统部分人员感知(表现为一个页面消息)。最早版本是后台管理系统轮训,每隔一段时间轮训一次,由于消息重要,每隔几秒就查一次。这样做明显很不雅!会消耗大量资...
  • zhangdehua678
  • zhangdehua678
  • 2017-12-27 16:40:44
  • 10142

Spring boot websocket消息推送

Spring boot webSocket消息推送
  • Veggiel
  • Veggiel
  • 2016-08-24 14:19:52
  • 3068

在Spring Boot框架下使用WebSocket实现消息推送

Spring Boot的学习持续进行中。前面两篇博客我们介绍了如何使用Spring Boot容器搭建Web项目(使用Spring Boot开发Web项目)以及怎样为我们的Project添加HTTPS的...
  • u012702547
  • u012702547
  • 2016-12-23 16:48:37
  • 55777

spring boot 集成websocket实现实时推送

websocket暂时能想到的应用是浏览器聊天和后台日志实时显示到前台。当后台启动程序后,等待前台连接,连接上之后,前后台就可以相互发送数据了。先贴上pom配置: org.sp...
  • alantuling_jt
  • alantuling_jt
  • 2017-11-06 20:38:36
  • 1301

spring boot 整合activemq 进行服务端消息推送(web页面)

最近公司的项目里有需要服务端向web端实时推送消息的需求,网上搜索了一番,有前端页面通过定时任务向后台发送ajax请求刷新,有使用第三方提供的消息服务(GoEasy),前者因为会有很多请求是无用的,容...
  • kingvslucy
  • kingvslucy
  • 2017-12-07 09:54:03
  • 1150

rabbitmq实例:基于java、基于springboot、基于html的消息推送

  • 2018年01月10日 11:59
  • 129KB
  • 下载

SpringMVC整合websocket实现消息推送及触发

1.创建websocket握手协议的后台 (1)HandShake的实现类 /** *Project Name: price *File Name: HandShake.java *Pac...
  • liuyunshengsir
  • liuyunshengsir
  • 2016-09-10 17:20:20
  • 15452

Spring Boot + WebSocket实现消息推送

Spring Boot + WebSocket实现消息推送 WebSocket介绍 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)...
  • SeaFishLoving
  • SeaFishLoving
  • 2018-03-15 13:40:47
  • 29

springboot+websocket+sockjs进行消息推送

一,消息推送的服务端 1.创建简单的springboot工程。pom配置如下:
  • PandaWang1989
  • PandaWang1989
  • 2017-02-04 15:39:33
  • 4514

Spring+Websocket实现消息的推送

  • 2017年10月11日 16:34
  • 1006KB
  • 下载
收藏助手
不良信息举报
您举报文章:使用spring boot +WebSocket实现(后台主动)消息推送 (一)
举报原因:
原因补充:

(最多只允许输入30个字)