Spring+rabbitmq+stomp build WebSocket message push (non-spring boot mode)

Source: Internet
Author: User
Tags stomp throwable rabbitmq


Objective:



Two years ago did Spring+activemq+stomp WS Push, that is easy to do, but now the company uses MQ middleware is RABBITMQ, so need to do WS communication through RABBITMQ. Search carefully search Baidu/Google, online through the spring Boot+rabbitmq+stomp Tutorial article is a lot of, unfortunately, the current project is not spring boot, can not be applied. Had to go to the tinker. After a few hours, and finally got out, hereby share with you.



RabbitMQ:



How to install is not the topic of this discussion, their own Baidu/Google. The RABBITMQ default comes with the Stomp plugin, but it needs to be enabled on its own. The command is:





Rabbitmq-plugins Enable Rabbitmq_stomp


Come on, give me a reference to the document address, http://www.rabbitmq.com/stomp.html. The default is to connect with the guest user, and the password is guest.



Here's a question, look at the RABBITMQ configuration file, the STOMP protocol port is 61613 by default, but the WS protocol connection is always not connected, so only with the Web Stomp port, the port number is 15674, this is different from ACTIVEMQ. (P.S. It is better to have a great God here, or to tell how to use 61613来)



Javascript:

Front-end code is the most convenient, the key is debugging is also easy, so first come:


var stompClient = null;

var headers = {
   login: 'guest',
   passcode: 'guest'
};

function wsConnect (url) {
     var ws = new SockJS (url);
     stompClient = Stomp.over (ws);

     // var ws = new WebSocket (url);
     // stompClient = Stomp.over (ws);

     // SockJS does not support heart-beat: disable heart-beats
     stompClient.heartbeat.outgoing = 0;
     stompClient.heartbeat.incoming = 0;

     stompClient.connect (headers, function (frame) {
         console.log ('Connected:' + frame);

         stompClient.subscribe ('/ topic / test', function (sms) {
             var obj = JSON.parse (sms.body)
             var count = obj.totalCount;

             console.log ("count:" + count);
         });

     });
}

And then it's connected to the chant.


$(function(){
    var url = "http://host:15674/stomp";
    wsConnect(url);
});  


Finish the preparation test, of course, choose Chrome, after the page load, open the console console, you can see the web socket connected, the front end is done.






Java:


Defines a Stompservice class that is specifically used to send stomp messages.


import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/ **
 * stomp service rabbitmq as middleware
 * @author Selwyn
 * @version $ Id: WebSocketConfig.java, v 0.1 9/7/2018 9:59 AM Selwyn Exp $
 * /
@Component
public class StompService {

    private static final String URL_TEMPLATE = "http: //% s:% s / stomp";

    @Value ("$ {rabbit.host}")
    private String host;

    //@Value("${rabbit.stomp.port} ")
    private Integer port = 15674;

    / **
     * Connect user name
     * /
    //@Value("${rabbit.stomp.login} ")
    private String login = "guest";
    / **
     * Connection password
     * /
    //@Value("${rabbit.stomp.passCode} ")
    private String passCode = "guest";

    private String url;

    @PostConstruct
    public void init ()
    {
        url = String.format (URL_TEMPLATE, host, port);
    }

    / **
     * Send stomp message
     * @param dest destination such as / topic / test
     * @param toSend the message to be sent
     * @param <T>
     * /
    public <T> void connectAndSend (String dest, T toSend)
    {
        WebSocketClient client = new StandardWebSocketClient ();

        List <Transport> transports = new ArrayList <> (1);
        transports.add (new WebSocketTransport (client));
        // Take the web stomp way, you must connect with socketjs, don't ask me why, I don't know
        WebSocketClient transport = new SockJsClient (transports);
        WebSocketStompClient stompClient = new WebSocketStompClient (transport);
        // The default payload type of StompSessionHandlerAdapter is String, so MessageConverter must be StringMessageConverter
        stompClient.setMessageConverter (new StringMessageConverter ());

        final CustomStompSessionHandler sessionHandler =
                new CustomStompSessionHandler (dest, toSend);

        WebSocketHttpHeaders headers = new WebSocketHttpHeaders ();
        headers.setSecWebSocketProtocol ("13");

        // Connect user name / password is also necessary, otherwise you can't connect
        StompHeaders sHeaders = new StompHeaders ();
        sHeaders.add ("login", this.login);
        sHeaders.add ("passcode", this.passCode);

        // Start connection, send stomp message after callback connection
        stompClient.connect (url, headers, sHeaders, sessionHandler);

        // To get the sending result synchronously, use CountDownLatch to do it or connect the future object of the result to get
    }

} 

Then writes the callback handler class.


Import com.alibaba.fastjson.JSON;
Import lombok.extern.slf4j.Slf4j;
Import org.springframework.messaging.simp.stomp.StompCommand;
Import org.springframework.messaging.simp.stomp.StompHeaders;
Import org.springframework.messaging.simp.stomp.StompSession;
Import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
 
 
/**
 * Custom stomp session callback handler
 * @author Selwyn
 * @version $Id: CustomStompSessionHandler.java, v 0.1 9/7/2018 3:43 PM Selwyn Exp $
 */
@Slf4j
Public class CustomStompSessionHandler extends StompSessionHandlerAdapter {
 
    /**
     * The object to be sent will be jsoned and transmitted.
     */
    Private Object toSend;
 
    /**
     * Destination, usually a topic address
     */
    Private String dest;
 
    Public CustomStompSessionHandler(String dest, Object toSend) {
        this.toSend = toSend;
        This.dest = dest;
    }
 
    @Override
    Public void handleFrame(StompHeaders headers, Object payload) {
        super.handleFrame(headers, payload);
    }
 
    @Override
    Public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
        super.afterConnected(session, connectedHeaders);
        String msg = JSON.toJSONString(toSend);
        Try{
            Session.send(dest, msg);
        }catch(Exception e)
        {
            Log.error("failed to send stomp msg({}) to destination {}", msg, dest);
        }finally {
            // finished closing 呗
            Session.disconnect();
        }
    }
 
    @Override
    Public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {
        super.handleException(session, command, headers, payload, exception);
        Log.error("stomp error: {}", exception);
    }
 
    @Override
    Public void handleTransportError(StompSession session, Throwable exception) {
        super.handleTransportError(session, exception);
        Log.error("stomp transport error: {}", exception);
    }
 
    Public void setToSend(Object toSend) {
        this.toSend = toSend;
    }
 
    Public void setDest(String dest) {
        This.dest = dest;
    }
} 


Write a controller or write a unit test method, here does not give the code, after the start of the service, you can test the message pushed, practice proves, really fragrant!



End:


In fact, the whole process is not finished, need to consider the connection interruption, and so on, the client and the service backend need to do a good job of reconnection mechanism. Through SOCKJS this way connection is no heartbeat mechanism, this than ACTIVEMQ belt stomp plug to Low. Personal advice, if you can use Spring boot, try to use that way to achieve stomp message push.





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.