Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Unread messages (small red dot), front end and RabbitMQ real-time message push practice, thief simple


May 31, 2021 Article blog


Table of contents


The article is reproduced from the public number: Something inside the programmer

A few days ago there was a small partner in the fan base asked: web page unread message (small red dot) how to achieve relatively simple, just this week has a similar development task on hand, the rope will be sorted out for small partners to refer to, maybe one day can be used.

 Unread messages (small red dot), front end and RabbitMQ real-time message push practice, thief simple1

web real-time message push, commonly used to implement more ways, but it is not far away from its parcel, the bottom layer is basically dependent on websocket MQTT protocol is no exception.

RabbitMQ build

RabbitMQ foundation is not detailed, self-Baidu step by step to do not have a problem, here mainly said two more important configuration.

1, open the mqtt protocol

RabbitMQ does not turn on MQTT protocol, so we are required to manually open the relevant plug-ins, while RabbitMQ MQTT protocol is divided into two types.

The first rabbitmq_mqtt provides interactive use with the back-end service, corresponding to port 1883

rabbitmq-plugins enable rabbitmq_mqtt

The second rabbitmq_web_mqtt provides interactive use with the front end, corresponding to port 15675

rabbitmq-plugins enable rabbitmq_web_mqtt 

Seeing the following display in the RabbitMQ management background indicates that the MQTT protocol was opened successfully and the middleware environment was built.

 Unread messages (small red dot), front end and RabbitMQ real-time message push practice, thief simple2

Using MQTT protocol, the default switch Exchange is amp.topic and the topic we subscribe to registers a client queue with Queues and Routing key is the theme we set up.

 Unread messages (small red dot), front end and RabbitMQ real-time message push practice, thief simple3

Service-side messages are sent

web real-time message push is generally one-way push, front-end receiving service-side push message display can be, so only the implementation of message sending can be.

1, mqtt client depends on the package

Introduce spring-integration-mqtt org.eclipse.paho.client.mqttv3 two toolkit implementations

<!--mqtt依赖包-->
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-mqtt</artifactId>
</dependency>
<dependency>
    <groupId>org.eclipse.paho</groupId>
       <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
    <version>1.2.0</version>
</dependency>

2, the sender of the message

Messages are simple to send, mainly to @ServiceActivator annotations, and you need to be aware of messageHandler.setAsync property, which can be blocked when sending messages in false mode is turned off if set to false.

@Configuration
public class IotMqttProducerConfig {


    @Autowired
    private MqttConfig mqttConfig;


    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setServerURIs(mqttConfig.getServers());
        return factory;
    }


    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }


    @Bean
    @ServiceActivator(inputChannel = "iotMqttInputChannel")
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(mqttConfig.getServerClientId(), mqttClientFactory());
        messageHandler.setAsync(false);
        messageHandler.setDefaultTopic(mqttConfig.getDefaultTopic());
        return messageHandler;
    }
}

When MQTT provides API for sending messages to the outside world, it needs to use @MessagingGateway annotations to provide a message gateway proxy, and the parameter defaultRequestChannel specifies channel sends the message binding.

There are three API interfaces that can be implemented, payload for the message sent, topic for the subject of the message sent, qos message quality.

@MessagingGateway(defaultRequestChannel = "iotMqttInputChannel")
public interface IotMqttGateway {


    // 向默认的 topic 发送消息
    void sendMessage2Mqtt(String payload);
    // 向指定的 topic 发送消息
    void sendMessage2Mqtt(String payload,@Header(MqttHeaders.TOPIC) String topic);
    // 向指定的 topic 发送消息,并指定服务质量参数
    void sendMessage2Mqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
}

Front-end message subscription

The front end uses paho-mqtt mqttws31.js implementation corresponding to the service side in much the same way as the traditional websocket approach, and the core method client = new Paho.MQTT.Client and various listening events, and the code is simple.

Note: To ensure the global uniqueness of the front and rear clientId I've solved this here with random numbers

<script type="text/javascript">
        // mqtt协议rabbitmq服务
        var brokerIp = location.hostname;
        // mqtt协议端口号
        var port = 15675;
        // 接受推送消息的主题
        var topic = "push_message_topic";


        // mqtt连接
        client = new Paho.MQTT.Client(brokerIp, port, "/ws", "clientId_" + parseInt(Math.random() * 100, 10));


        var options = {
            timeout: 3, //超时时间
            keepAliveInterval: 30,//心跳时间
            onSuccess: function () {
                console.log(("连接成功~"));
                client.subscribe(topic, {qos: 1});
            },
            onFailure: function (message) {
                console.log(("连接失败~" + message.errorMessage));
            }
        };
        // 考虑到https的情况
        if (location.protocol == "https:") {
            options.useSSL = true;
        }
        client.connect(options);
        console.log(("已经连接到" + brokerIp + ":" + port));


        // 连接断开事件
        client.onConnectionLost = function (responseObject) {
            console.log("失去连接 - " + responseObject.errorMessage);
        };


        // 接收消息事件
        client.onMessageArrived = function (message) {
            console.log("接受主题: " + message.destinationName + "的消息: " + message.payloadString);
            $("#arrivedDiv").append("<br/>"+message.payloadString);
            var count = $("#count").text();
            count = Number(count) + 1;
            $("#count").text(count);
        };


        // 推送给指定主题
        function sendMessage() {
            var a = $("#message").val();
            if (client.isConnected()) {
                var message = new Paho.MQTT.Message(a);
                message.destinationName = topic;
                client.send(message);
            }
        }
    </script>

Test

There's not a lot of code on the front and back ends, so let's test it and get a page to see how it works.

Start by sending a message with postman impersonation of the backend

http://127.0.0.1:8080/fun/sendMessage?message=我是程序员内点事&topic=push_message_topic

 Unread messages (small red dot), front end and RabbitMQ real-time message push practice, thief simple4

Take another look at the effect of the front-end subscription message, see the message is pushed to the front end in real time, here only the number of unread message statistics, generally also do unread message details list.

 Unread messages (small red dot), front end and RabbitMQ real-time message push practice, thief simple5

summary

Unread messages are a very common feature, whether web or mobile systems are required modules, MQTT protocol is only one way to implement, or it is necessary to master a method. Exactly what tools to implement or depends on the specific business scenario and learning costs, like I used RabbitMQ to do also take into account some of the operational costs in it.

The above is W3Cschool编程狮 about unread messages (little red dot), the front end and RabbitMQ real-time message push practice, the thief simple , the relevant introduction, I hope to help you.