1 网址
MQTT BROKER
https://github.com/hivemq/hivemq-community-edition
https://github.com/mtsoleimani/cassandana
https://github.com/longkerdandy/mithqtt
https://github.com/Cicizz/jmqtt
https://github.com/Wizzercn/MqttWk
MQTT CLIENT
https://github.com/hivemq/hivemq-mqtt-client
https://hivemq.github.io/hivemq-mqtt-client/
2 MqttSender.java
package com.sunxu.mqttclient;
import com.hivemq.client.mqtt.datatypes.MqttQos;
import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;
import com.hivemq.client.mqtt.mqtt3.Mqtt3BlockingClient;
import com.hivemq.client.mqtt.mqtt3.Mqtt3Client;
import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@Component
@Slf4j
public class MqttSender {
@PostConstruct
public void subscribe() throws InterruptedException {
Mqtt3BlockingClient client = Mqtt3Client.builder()
.identifier(UUID.randomUUID().toString())
.serverHost("127.0.0.1")
.serverPort(8885)
.buildBlocking();
client.connect();
client.toAsync().subscribeWith()
.topicFilter("test/topic")
.qos(MqttQos.AT_LEAST_ONCE)
.callback(publish -> {
System.out.println("receive topic :" + publish.getTopic() + " message: " +
new String(publish.getPayloadAsBytes(), StandardCharsets.UTF_8));
})
.send();
Mqtt3AsyncClient publish_client = Mqtt3Client.builder()
.identifier(UUID.randomUUID().toString())
.serverHost("127.0.0.1")
.serverPort(8885)
.buildAsync();
for (int i=0;i<1000;i++) {
if(i==10) break;
final String j = String.valueOf(i);
publish_client.connect()
.thenCompose(connAck -> publish_client.publishWith().topic("test/topic").payload(j.getBytes()).send())
.thenCompose(publishResult -> publish_client.disconnect());
Thread.sleep(1000);
}
client.disconnect();
}
}
3 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sunxu</groupId>
<artifactId>mqttclient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mqttclient</name>
<description>mqttclient</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.hivemq</groupId>
<artifactId>hivemq-mqtt-client</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.hivemq</groupId>
<artifactId>hivemq-mqtt-client-websocket</artifactId>
<version>1.3.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.hivemq</groupId>
<artifactId>hivemq-mqtt-client-proxy</artifactId>
<version>1.3.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.hivemq</groupId>
<artifactId>hivemq-mqtt-client-epoll</artifactId>
<version>1.3.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.hivemq</groupId>
<artifactId>hivemq-mqtt-client-reactor</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.4</version>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
import com.fasterxml.jackson.core.JsonProcessingException;
import com.hivemq.client.mqtt.MqttGlobalPublishFilter;
import com.hivemq.client.mqtt.datatypes.MqttQos;
import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedContext;
import com.hivemq.client.mqtt.lifecycle.MqttClientConnectedListener;
import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext;
import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener;
import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hivemq.client.mqtt.mqtt5.lifecycle.Mqtt5ClientConnectedContext;
import com.hivemq.client.mqtt.mqtt5.message.auth.Mqtt5SimpleAuth;
import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.RunnableWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import static
import static java.nio.charset.StandardCharsets.UTF_8;
@Slf4j
@Service
public class ClientMessageDispatchService implements MessageDispatchService {
@Autowired
private MqttClientConfig mqttClientConfig;
@Autowired
private HttpAgent httpAgent;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ThreadPoolTaskExecutor clusterSendMessageExecutor;
@Autowired
private SessionManager sessionManager;
private Mqtt5BlockingClient client;
private Mqtt5AsyncClient asyncClient;
private boolean registerSuccess = false;
@Override
public void MqttConnect() throws JsonProcessingException {
Mqtt5SimpleAuth auth = Mqtt5SimpleAuth.builder()
.username(mqttClientConfig.getUsername())
.password(UTF_8.encode(mqttClientConfig.getPassword()))
.build();
client = Mqtt5Client.builder()
.identifier(mqttClientConfig.getClientid())
.serverHost(mqttClientConfig.getBrokeraddress())
.serverPort(Integer.parseInt(mqttClientConfig.getBrokerport()))
.sslConfig()
.trustManagerFactory(InsecureTrustManagerFactory.INSTANCE)
.applySslConfig()
.addConnectedListener(new MqttClientConnectedListener() {
@Override
public void onConnected(MqttClientConnectedContext context) {
log.info("mqttclient: {} is connected",mqttClientConfig.getClientid());
Mqtt5ClientConnectedContext mqtt5ClientConnectedContext = (Mqtt5ClientConnectedContext) context;
Mqtt5ConnAck mqtt5ConnAck = mqtt5ClientConnectedContext.getConnAck();
boolean isSessionPresent = mqtt5ConnAck.isSessionPresent();
if (!isSessionPresent) {
log.info("【CLIENT-SUB】client: {} subscribe to topic {}:",mqttClientConfig.getClientid(),mqttClientConfig.getIntertopic());
asyncClient.subscribeWith()
.topicFilter(mqttClientConfig.getIntertopic())
.qos(MqttQos.AT_LEAST_ONCE)
.send();
}
}
})
.addDisconnectedListener(new MqttClientDisconnectedListener() {
@Override
public void onDisconnected(MqttClientDisconnectedContext context) {
log.warn("mqttclient: {} is disconnected",mqttClientConfig.getClientid());
if (!registerSuccess) {
log.warn("mqttclient: {} registration failed",mqttClientConfig.getClientid());
try {
if (MqttRegister()) {
setRegisterSuccess(true);
}
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
})
.automaticReconnectWithDefaultConfig()
.simpleAuth(auth)
.sslConfig()
.trustManagerFactory(InsecureTrustManagerFactory.INSTANCE)
.applySslConfig()
.buildBlocking();
asyncClient = client.toAsync();
asyncClient.publishes(MqttGlobalPublishFilter.SUBSCRIBED, mqtt5Publish -> {
byte[] msg = mqtt5Publish.getPayloadAsBytes();
StoredMessage storedMessage = SerializeHelper.deserialize(msg, StoredMessage.class);
if (storedMessage != null) {
storedMessage.setReceiveTime(System.currentTimeMillis());
clusterSendMessageExecutor.submit(RunnableWrapper.of(() ->
sessionManager.publishToLocalSubscribers(storedMessage)
));
} else {
throw new BusinessException(CG_EMPTY_MQTT_MESSAGE);
}
});
client.connectWith()
.simpleAuth(auth)
.keepAlive(235)
.send();
}
@Override
public void MqttPublish(StoredMessage storedMessage) {
byte[] bytedata = SerializeHelper.serialize(storedMessage);
asyncClient.publishWith()
.topic(mqttClientConfig.getIntertopic())
.qos(MqttQos.AT_LEAST_ONCE)
.payload(bytedata)
.send();
}
@Override
public boolean MqttRegister() throws JsonProcessingException {
UspInfoDTO uspInfoDTO = UspInfoDTO.builder()
.user(mqttClientConfig.getUsername())
.host("localhost")
.password(mqttClientConfig.getPassword())
.build();
HashMap<String, Object> params = objectMapper.readValue(objectMapper.writeValueAsString(uspInfoDTO), HashMap.class);
String response = httpAgent.post(mqttClientConfig.getRegisterurl(), params);
if (response.contains("successfully registered")) {
log.info("register to msg broker success, response is {}", response);
return true;
}
if(response.contains("already registered")) {
log.info("register to msg broker success, response is {}", response);
return true;
}
return false;
}
@Override
public void MqttShowdown() {
client.disconnect();
return;
}
public boolean getRegisterSuccess() {
return this.registerSuccess;
}
public void setRegisterSuccess(boolean registerSuccess) {
this.registerSuccess = registerSuccess;
return;
}
}