SpringBoot整合mqtt(搭建EMQ X消息服务器)
2021年新的编程之旅就从这篇文章开始吧!!!
祝大家新的一年能升职加薪,身体健康,不掉头发!!!
1.安装EMQ X: Linux下执行 curl https://repos.emqx.io/install_emqx.sh | bash
(更多关于EMQ X 详细信息转至链接: https://www.emqx.io/docs/zh/v5/deploy/install-docker.html.
2.安装完成访问ip+端口,如192.168.10.254:18083(默认端口),默认账号:admin 密码: public,登录后进入首页:
3.建立Springboot项目,引入依赖:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
</dependency>
4.配置mqtt相关参数:
#MQTT配置信息
#MQTT-服务器连接地址
ximo.mqtt.host=tcp://192.168.10.254:1883
#MQTT-连接服务器默认客户端ID
ximo.mqtt.clientid=mqttjs_cloud
#MQTT-用户名
ximo.mqtt.username=admin
#MQTT-密码
ximo.mqtt.password=public
#连接超时
ximo.mqtt.timeout=1000
#心跳检查时间
ximo.mqtt.keepalive = 10
5.Springboot 获取mqtt连接
5.1 项目结构
5.2 mqtt配置类,获取mqtt连接
@Component
@Configuration
@ConfigurationProperties(MqttConfiguration.PREFIX)
public class MqttConfiguration {
@Autowired
private MqttPushClient mqttPushClient;
//指定配置文件application-local.properties中的属性名前缀
public static final String PREFIX = "ximo.mqtt";
private String host;
private String clientId;
private String userName;
private String password;
private String topic;
private int timeout;
private int keepAlive;
public String getClientid() {
return clientId;
}
public void setClientid(String clientid) {
this.clientId = clientid;
}
public String getUsername() {
return userName;
}
public void setUsername(String username) {
this.userName = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getKeepalive() {
return keepAlive;
}
public void setKeepalive(int keepalive) {
this.keepAlive = keepalive;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
/**
* 连接至mqtt服务器,获取mqtt连接
* @return
*/
@Bean
public MqttPushClient getMqttPushClient() {
//连接至mqtt服务器,获取mqtt连接
mqttPushClient.connect(host, clientId, userName, password, timeout, keepAlive);
//一连接mqtt,就订阅默认需要订阅的主题(如test_queue)
new MqttSubClient(mqttPushClient);
return mqttPushClient;
}
}
5.3 连接至EMQ X 服务器,获取mqtt连接,发布消息
@Slf4j
@Component
public class MqttPushClient{
@Autowired
private PushCallback pushCallback;
private static MqttClient client;
public static void setClient(MqttClient client) {
MqttPushClient.client = client;
}
public static MqttClient getClient() {
return client;
}
public void connect(String host, String clientID, String username, String password, int timeout, int keepalive) {
MqttClient client;
try {
client = new MqttClient(host, clientID, new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true);
options.setUserName(username);
options.setPassword(password.toCharArray());
options.setConnectionTimeout(timeout);
options.setKeepAliveInterval(keepalive);
MqttPushClient.setClient(client);
try {
//设置回调类
client.setCallback(pushCallback);
//client.connect(options);
IMqttToken iMqttToken = client.connectWithResult(options);
boolean complete = iMqttToken.isComplete();
log.info("MQTT连接"+(complete?"成功":"失败"));
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发布,默认qos为0,非持久化
*
* @param topic 主题名
* @param pushMessage 消息
*/
public void publish(String topic, String pushMessage) {
publish(0, false, topic, pushMessage);
}
/**
* 发布
*
* @param qos
* @param retained
* @param topic
* @param pushMessage
*/
public void publish(int qos, boolean retained, String topic, String pushMessage) {
MqttMessage message = new MqttMessage();
message.setQos(qos);
message.setRetained(retained);
message.setPayload(pushMessage.getBytes());
MqttTopic mTopic = client.getTopic(topic);
if (null == mTopic) {
log.error("主题不存在:{}",mTopic);
}
try {
mTopic.publish(message);
} catch (Exception e) {
log.error("mqtt发送消息异常:",e);
}
}
}
5.4 订阅消息主题,订阅成功后会在消息回调类接收相关主题的消息
@Slf4j
@Component
public class MqttSubClient {
public MqttSubClient(MqttPushClient client){
subScribeDataPublishTopic();
}
private void subScribeDataPublishTopic(){
//订阅test_queue主题
subscribe("test_queue");
}
/**
* 订阅某个主题,qos默认为0
*
* @param topic
*/
public void subscribe(String topic) {
subscribe(topic, 0);
}
/**
* 订阅某个主题
*
* @param topic 主题名
* @param qos
*/
public void subscribe(String topic, int qos) {
try {
MqttClient client = MqttPushClient.getClient();
if (client == null) return;
client.subscribe(topic, qos);
log.info("订阅主题:{}",topic);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
5.5 消息回调,处理接收的消息
@Slf4j
@Component
public class PushCallback implements MqttCallback {
@Autowired
private MqttConfiguration mqttConfiguration;
@Override
public void connectionLost(Throwable cause) { // 连接丢失后,一般在这里面进行重连
log.info("连接断开,正在重连");
MqttPushClient mqttPushClient = mqttConfiguration.getMqttPushClient();
if (null != mqttPushClient) {
mqttPushClient.connect(mqttConfiguration.getHost(), mqttConfiguration.getClientid(), mqttConfiguration.getUsername(),
mqttConfiguration.getPassword(), mqttConfiguration.getTimeout(), mqttConfiguration.getKeepalive());
log.info("已重连");
}
}
/**
* 发送消息,消息到达后处理方法
* @param token
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
/**
* 订阅主题接收到消息处理方法
* @param topic
* @param message
*/
@Override
public void messageArrived(String topic, MqttMessage message) {
// subscribe后得到的消息会执行到这里面,这里在控制台有输出
log.info("接收消息主题 : " + topic);
log.info("接收消息Qos : " + message.getQos());
log.info("接收消息内容 : " + new String(message.getPayload()));
}
}
6.测试类
@RestController
@RequestMapping("mqttDemo")
public class MqttDemoController {
@Autowired
private MqttPushClient mqttPushClient;
/**
* 通过MqttPushClient类publish方法的发送"这是一条测试消息"到名为"test_queue"的主题,如果需要拿到这条消息,
* 需要在MqttSubClient类的subScribeDataPublishTopic方法进行配置和订阅该主题(这个DEMO已经配置好,并在连接mqtt服务器时就已经订阅),
* 配置完成后 PushCallBack类的messageArrived方法会接收到已订阅主题接收到的消息(订阅主题后可以在该方法中处理接收到的消息)
*/
@RequestMapping("testPublishMessage1")
public void testPublishMessage() {
mqttPushClient.publish("test_queue","这是一条测试消息");
}
@RequestMapping("testPublishMessage2")
public void testPublishMessage2(String message){
mqttPushClient.publish("test_queue",message);
}
}
获取完整代码请点击 Springboot整合mqtt完整Demo(记得star哦)
最新以及优化过的地址Gitee下载地址