由于做数据大屏展示,需要实时刷新数据(按秒),AJAX请求实现长轮询效率太低,所以就想到了websocket长连接,WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端,只需要一次连接,还有心跳检测,重新连接等。
我们这里采用服务器端主动向客户端消息推送。(广播方式)
不多说,直接上代码!
springboot项目,引入组件
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-websocket</artifactId> 4 </dependency>
服务端代码:
1.socket配置文件
1 @Configuration 2 @EnableWebSocketMessageBroker //注解开启STOMP协议来传输基于代理的消息,此时控制器支持使用@MessageMapping 3 public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { 4 5 @Override 6 public void configureMessageBroker(MessageBrokerRegistry registry) { 7 registry.enableSimpleBroker("/queue","/topic");//topic用来广播,订阅,推送,prefix(topic),queue用来实现p2p 8 //全局使用消息订阅前缀 9 // 例如客户端发送消息的目的地为/app/send,则对应控制层@MessageMapping(“/send”) 10 // 客户端订阅主题的目的地为/app/subscribe,则对应控制层@SubscribeMapping(“/subscribe”) 11 registry.setApplicationDestinationPrefixes("/app"); 12 //点对点配置消息前缀 13 //registry.setUserDestinationPrefix("/user"); 14 } 15 16 17 18 @Override 19 public void registerStompEndpoints(StompEndpointRegistry registry) { 20 //用于客户端连接地址 21 registry.addEndpoint("/webServer") 22 //处理接口请求 23 // .setHandshakeHandler(new MsgHandler()) 24 //解决跨域问题 25 .setAllowedOrigins("*"); 26 //拦截器,拦截握手前后消息 27 // .addInterceptors(new MyHandshakeInterceptor()); 28 //withSockJS 由于使用reconnection-websocket.min.js,暂时不需要 29 //registry.addEndpoint("/queueServer").withSockJS();//注册两个STOMP的endpoint,分别用于广播和点对点 30 }
2.服务端消息推送
@Autowired
private SimpMessagingTemplate template;
//订阅消息 @MessageMapping("/screen1/order/all/info/{date}") public void allOrder(@DestinationVariable("date") String date) { logger.info("订阅交易汇总统计:{}",date); Map<String,Object> map = null; if("day".equals(date)){ map = screenController.getAmtDayAll(); }else{ map = screenController.getAmtMonthAll(); } template.convertAndSend("/topic/info/"+date,map); }
引入客户端JS结合echarts进行数据实时展现
有个头疼的问题,浏览器总是打印服务器端返回的数据,打开浏览器调试工具,发现在stomp.min.js中打印的,接下来看看怎么去掉呢?
定位了一下,发现是stomp.min.js 中118行。跟踪后,e.log(t)是罪魁祸首,t就是打印的数据。改为"",很棒!你们是怎么解决这个问题的呢
发现这种写法很棒:(e = window.console) != null
116 r.prototype.debug = function(t) { 117 var e;
118 return typeof window !== "undefined" && window !== null ? (e = window.console) != null ? "" : void 0 : void 0
119 //return typeof window !== "undefined" && window !== null ? (e = window.console) != null ? e.log(t) : void 0 : void 0
};
1 <script src="../js/websocket/reconnecting-websocket.min.js" type="text/javascript"></script>//解决服务器断开,客户端主动重连问题 2 <script src="../js/websocket/stomp.min.js" type="text/javascript"></script> 3 <script src="../js/jquery/jquery.min.js" type="text/javascript"></script>
1 /**********************************************websocket****************************************/ 2 var stompClient = null; 3 4 function connect() { 5 //如果掉线5秒尝试重连 6 var socket = new ReconnectingWebSocket("ws://localhost:8888/webServer", null, {debug: false, reconnectInterval: 5000}); 7 stompClient = Stomp.over(socket); 8 stompClient.connect({}, function(frame) { 9 10 //订阅消息 11 subscribeAddTotalData(); 12 13 }); 14 } 15 16 function sendInfo(sendPath){ 17 var messageJson = JSON.stringify({}); 18 stompClient.send(sendPath,{},messageJson); 19 } 20 //主动发送消息
function getAddTotalData() {
sendInfo("/app/info/");
}
21
22 function subscribeAddTotalData() {
23 //订阅消息路径
24 stompClient.subscribe('/topic/info/',function (response) {
25 //获取终端详细数据
26 var body = response.body;
27 var data = JSON.parse(body);
28 //处理数据
29
30 });
31 }
效果图
![](https://img2018.cnblogs.com/blog/1523679/201811/1523679-20181101201520299-1328764106.png)