A few days ago, a small partner in the fan group asked: web
How to implement the unread messages (small red dots) on the page is relatively simple. Just this week, there is a similar development task on hand, so I simply sorted it out for my friends’ reference. Days can be used.
Previously, in "springboot + rabbitmq for smart home" , it was mentioned that rabbitmq
the MQTT
protocol can be used to push the instructions of the smart home. It also mentioned that the message push can be MQTT
done web
with the protocol , and the unread message ( 小红点
) function is just applied to the real-time message push Up.
MQTT
I won’t go into details about the agreement anymore. If you haven’t touched it before, let’s review the previous article. Today, it’s still practice-oriented!
web
There are many ways to implement real-time message push on the end, but it is always the same. The bottom layer basically depends on it websocket
, and the MQTT
protocol is no exception.
RabbitMQ build
RabbitMQ
I won’t go into details about the basic construction of Baidu. It’s not a big problem to do it step by step with Baidu. Here are two more important configurations.
1. Open the mqtt protocol
By default, RabbitMQ
it is not open MQTT
protocol, so we need to manually open the associated plug-ins, and RabbitMQ
the MQTT
agreement is divided into two.
The first one rabbitmq_mqtt
provides interactive use with back-end services and corresponds to the port 1883
.
rabbitmq-plugins enable rabbitmq_mqtt
The second type rabbitmq_web_mqtt
provides interactive use with the front end and corresponds to the port 15675
.
rabbitmq-plugins enable rabbitmq_web_mqtt
If RabbitMQ
you see the following display in the management background, it means that the MQTT
protocol has been opened successfully, and the middleware environment has been set up.
Protocol corresponding port number
The MQTT
default exchange Exchange
of the protocol is used amp.topic
, and the topic we subscribe to will Queues
register a client queue, and the route Routing key
is the topic we set.
Switch information
Server message sending
web
Terminal real-time message push is generally a one-way push, and the front-end receives the message pushed by the server to display, so only message sending is required.
1. Mqtt client dependency package
Introduction spring-integration-mqtt
, org.eclipse.paho.client.mqttv3
implementation of two toolkits
<!--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. Message sender
Message sending is relatively simple, mainly applied to @ServiceActivator
annotations, you need to pay attention to the messageHandler.setAsync
attributes, if set to false
, it may block when the asynchronous mode is turned off to send messages.
@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;
}
}
MQTT
When sending messages to the outside world API
, you need to use @MessagingGateway
annotations to provide a message gateway proxy, and the parameters defaultRequestChannel
specify the binding of sending messages channel
.
Three types of API
interfaces can be implemented , payload
including the message topic
sent, the subject of the qos
message sent, and the 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 news subscription
The front-end is implemented using tools corresponding to the server paho-mqtt
mqttws31.js
. The implementation is similar to the traditional websocket
way. The core methods client = new Paho.MQTT.Client
and various monitoring events are relatively simple in code.
Note : To ensure clientId
the global uniqueness of the front and back ends , I simply use random numbers here to solve
<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 are not many front-end and back-end codes. Let's test it and make a page to see the effect.
First postman
send the message with the simulated backend
http://127.0.0.1:8080/fun/sendMessage?message=我是程序员内点事&topic=push_message_topic
Simulate sending messages
Look at the effect of the front-end subscribing to messages again, and see that the messages are pushed to the front-end in real time. Here, only the number of unread messages is counted, and generally a list of unread messages is also made.
Real-time message push animation
to sum up
Unread messages is a very common function, no matter whether it is a web
terminal or a mobile terminal system, it is a necessary module. The MQTT
protocol is only one of the implementation methods, or it is necessary to master a method. The specific tools used to implement it still depend on the specific business scenarios and learning costs. For example, I RabbitMQ
also consider some operation and maintenance costs in it.
The complete code address of this article :https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-mqtt-messagepush