SpringGuids-websocket推送消息

SpringGuids-websocket推送消息

Tags: WebSocket SpringBoot

摘要

websocket主动推送消息,springboot,websocket,stomp.js,sockjs-0.3.4.js

websocket了解

websocket跟http是完全不同的两个协议。
websocket跟http的关系只是websocket建立连接的时候依靠http。
后面的通讯,浏览亲客户端发送请求到ws服务,还是ws服务主动推送到浏览器客户端都在这一个建立好的连接上,所以效率要比http轮询高的很多。

场景介绍

服务器端有一些定时任务生成消息内容,要经常通知给网页端,网页端不可能不停的询问服务器端有没有消息,用websocket即可实现:在建立websocket连接的之后,网页端被动接受服务器端的通知。

代码分析

网页端

<!DOCTYPE html>
<html>
<head>
    <title>Hello WebSocket</title>
    <script src="jquery-1.12.4.min.js"></script>
    <script src="sockjs-0.3.4.js"></script>
    <script src="stomp.js"></script>
    <script type="text/javascript">
        var stompClient = null;

        function setConnected(connected) {
            document.getElementById('connect').disabled = connected;
            document.getElementById('disconnect').disabled = !connected;
            document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
            document.getElementById('response').innerHTML = '';
        }

        function connect() {
            var socket = new SockJS('/ws_connect');
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function (frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/echo_service', function (rs) {
                    showEcho(rs.body);
                });
            });
        }

        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            console.log("Disconnected");
        }

        function sendName() {
            var name = document.getElementById('name').value;
            stompClient.send("/app/hello_send", {}, JSON.stringify({'name': name}));
        }

        function showEcho(message) {
            var response = document.getElementById('response');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            p.appendChild(document.createTextNode(message));
            response.appendChild(p);
            $('html,body').scrollTop($(window).scrollTop() + $(window).height());
        }


    </script>
</head>
<body onload="disconnect();connect();">
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being
    enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div>
    <div>
        <button id="connect" onclick="connect();">Connect</button>
        <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
    </div>
    <div id="conversationDiv">
        <p id="response"></p>
    </div>
</div>

</body>
</html>

主要看

stompClient.subscribe('/topic/echo_service', function (rs) {
                    showEcho(rs.body);
                });

表示等待服务器端推送消息到当前网页上来
服务器端推送的地址肯定是/topic/echo_service

/ws_connect 是约定好的建立websocket连接的地址

socketjs

SockJS 是一个浏览器上运行的 JavaScript 库,如果浏览器不支持 WebSocket,该库可以模拟对 WebSocket 的支持,实现浏览器和 Web 服务器之间低延迟、全双工、跨域的通讯通道。

stomp

Stomp 提供了客户端和代理之间进行广泛消息传输的框架。Stomp 是一个非常简单而且易用的通讯协议实现,尽管代理端的编写可能非常复杂,但是编写一个 Stomp 客户端却是很简单的事情,另外你可以使用 Telnet 来与你的 Stomp 代理进行交互。

服务器端

服务器端配置建立连接的地址,配置服务器端的地址前缀,网页端地址前缀

package net.javablog;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");// 指向客户端
        config.setApplicationDestinationPrefixes("/app");//指向服务端
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws_connect").withSockJS();//指定websocket连接的地址
    }


}

定时任务发送消息到网页端指定的订阅地址

package net.javablog;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class Job {

    @Autowired
    private SimpMessagingTemplate template;


    @Scheduled(fixedRate = 2000)
    public void echo2send() {
        String time = new Date().toLocaleString();
        System.out.println(time);
        template.convertAndSend("/topic/echo_service", "测试内容," + time);
    }



}

代码地址

https://coding.net/u/javacore/p/spring-guides-study/git/tree/master/spring-websocket-push

演示

双击视频 全屏观看更清楚