准备工作:先在windows或者linux安装一个apollo,因为mqtt的连接,本质是Tcp连接。
1.在首先准备一个空的maven项目,下面引入依赖包。
<?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.6.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>mqtt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mqtt</name>
<description>mqtt demo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.定义MQTT相关的配置
server:
port: 8089
#mqtt连接的必要信息
mqtt:
param:
qos: 2
#mqtt连接是tcp的连接方式,注意路径
host: tcp://127.0.0.1:61613
username: admin
password: password
keepAlive: 30
timeOut: 60
topic1: com.xxx.topic1
topic2: com.xxx.topic2
topic3: com.xxx.topic3
topic4: com.xxx.topic4
3.通过工厂方法创建MQTT连接
package com.example.mqtt.factory;
import com.example.mqtt.listener.MqttListener;
import com.example.mqtt.model.MqttConfig;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.util.UUID;
/**
* @className:@MqttClientFactory
* @Description:连接工厂,通过bean的方式注入
* @Author:
* @Version:1.0
**/
@Configuration
public class MqttClientFactory {
@Autowired
private MqttConfig mqttConfig;
private Logger logger = LoggerFactory.getLogger(MqttClientFactory.class);
@Bean
public MqttClient mqttClient() {
MemoryPersistence persistence = new MemoryPersistence();
MqttClient mqttClient = null;
try {
mqttClient = new MqttClient(mqttConfig.getHost(), UUID.randomUUID().toString(),persistence);
} catch (MqttException e) {
logger.info("mqtt连接失败!!!");
e.printStackTrace();
}
MqttConnectOptions options = new MqttConnectOptions();
options.setConnectionTimeout(mqttConfig.getTimeOut().intValue());
options.setUserName(mqttConfig.getUsername());
options.setPassword(mqttConfig.getPassword().toCharArray());
options.setAutomaticReconnect(true);
options.setConnectionTimeout(100000);
options.setKeepAliveInterval(20000);
options.setCleanSession(true);
try {
mqttClient.connect(options);
} catch (MqttException e) {
e.printStackTrace();
}
logger.info("mqtt连接成功!!!");
return mqttClient;
}
}
4.创建mqtt回调类。
package com.example.mqtt.listener;
import com.example.mqtt.model.MqttConfig;
import org.eclipse.paho.client.mqttv3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @className:@MqttListener
* @Description:监听MQTT的消息
* @Author:
* @Version:1.0
**/
public class MqttListener implements MqttCallbackExtended {
private Logger logger = LoggerFactory.getLogger(MqttListener.class);
@Override
public void connectComplete(boolean b, String s) {
}
@Override
public void connectionLost(Throwable throwable) {
logger.info("正在连接.....");
}
@Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
logger.info("收到消息----");
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
logger.info("传输完成----");
}
}
5.创建信息发布类
package com.example.mqtt.publish;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @className:@MessagePublish
* @Description:消息发布类
* @Author:
* @Version:1.0
**/
@Component
public class MessagePublish {
@Autowired
private MqttClient mqttClient;
private Logger logger = LoggerFactory.getLogger(MessagePublish.class);
public boolean isPublish(String topic,String message,int qos){
try {
mqttClient.publish(topic,message.getBytes(),qos,true);
logger.info("mqtt消息发布成功!!");
} catch (MqttException e) {
e.printStackTrace();
logger.info("mqtt消息发布失败!!!!");
return false;
}
return true;
}
}
6.创建批量订阅BaseController基类
package com.example.mqtt.controller;
import com.example.mqtt.model.MqttConfig;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
/**
* @className:@BaseMqttController
* @Description:其他Controller类的创建必须要继承此类
* @Author:
* @Version:1.0
**/
public class BaseMqttController {
@Autowired
private MqttConfig configParam;
@Autowired
private MqttClient mqttClient;
private Logger logger = LoggerFactory.getLogger(BaseMqttController.class);
@PostConstruct
public void subscribe(){
IMqttMessageListener topicListener1 = new IMqttMessageListener() {
@Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
logger.info("接收到消息topic1{}",mqttMessage);
}
};
IMqttMessageListener topicListener2 = new IMqttMessageListener() {
@Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
logger.info("接收到消息topic2{}",mqttMessage);
}
};
IMqttMessageListener topicListener3 = new IMqttMessageListener() {
@Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
logger.info("接收到消息topic3{}",mqttMessage);
}
};
//订阅的所有主题
String topics[] = {
configParam.getTopic1(),
configParam.getTopic2(),
configParam.getTopic3(),
};
//监听所有的监听事件
IMqttMessageListener listens[]= {
topicListener1,
topicListener2,
topicListener3
};
//qoss 服务质量信息
int qoss[] = {
configParam.getQos(),
configParam.getQos(),
configParam.getQos()
};
try {
mqttClient.subscribe(topics,qoss,listens);
logger.info("批量订阅成功---------");
} catch (MqttException e) {
e.printStackTrace();
}
}
}
7.创建测试的Controller
package com.example.mqtt.controller;
import com.example.mqtt.model.MqttConfig;
import com.example.mqtt.publish.MessagePublish;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @className:@MqttController
* @Description:测试MQtt发信息和收信息的能力
* @Author:
* @Version:1.0
**/
@RestController
@RequestMapping("/")
public class MqttController extends BaseMqttController{
@Autowired
private MessagePublish publish;
private Logger logger = LoggerFactory.getLogger(MqttController.class);
@Autowired
private MqttConfig config;
@GetMapping("/sendMessage")
public Map<String,Object>sendMessage(){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String nowDate = dateFormat.format(new Date());
boolean sendTopic1 = publish.isPublish(config.getTopic1(),"我是topic1,发送了一条MQTT的消息"+nowDate,2);
boolean sendTopic2 = publish.isPublish(config.getTopic2(),"我是topic2,发送了一条MQTT的消息"+nowDate,2);
boolean sendTopic3 = publish.isPublish(config.getTopic3(),"我是topic3,发送了一条MQTT的消息"+nowDate,2);
List<Boolean>isSend = new ArrayList<>();
isSend.add(sendTopic1);
isSend.add(sendTopic2);
isSend.add(sendTopic3);
Map<String,Object> res = new HashMap<>();
res.put("code",200);
res.put("msg","发送成功!");
res.put("data",isSend);
return res;
}
}
8.创建配置文件实体类
package com.example.mqtt.model;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* @className:@MqttConfig
* @Description:配置实体类
* @Author:
* @Version:1.0
**/
@Configuration
@Data
public class MqttConfig {
//连接主机
@Value("${mqtt.param.host}")
private String host;
//服务消息质量
@Value("${mqtt.param.qos}")
private Integer qos;
//用户名
@Value("${mqtt.param.username}")
private String username;
//密码
@Value("${mqtt.param.password}")
private String password;
//主题
@Value("${mqtt.param.topic1}")
private String topic1;
@Value("${mqtt.param.topic2}")
private String topic2;
@Value("${mqtt.param.topic3}")
private String topic3;
@Value("${mqtt.param.keepAlive}")
private Long keepAlive;
//超时时间
@Value("${mqtt.param.timeOut}")
private Long timeOut;
}
9.下面是运行结果,如果你的运行结果与下面结果一致,那么恭喜你,已经入门MQTT.
"C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=64629 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=localhost -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-javaagent:E:\IDEA\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar=64632:E:\IDEA\IntelliJ IDEA 2018.2.5\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;D:\project\mqtt\target\classes;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter\2.6.4\spring-boot-starter-2.6.4.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot\2.6.4\spring-boot-2.6.4.jar;C:\Users\admin\.m2\repository\org\springframework\spring-context\5.3.16\spring-context-5.3.16.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.6.4\spring-boot-autoconfigure-2.6.4.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.6.4\spring-boot-starter-logging-2.6.4.jar;C:\Users\admin\.m2\repository\ch\qos\logback\logback-classic\1.2.10\logback-classic-1.2.10.jar;C:\Users\admin\.m2\repository\ch\qos\logback\logback-core\1.2.10\logback-core-1.2.10.jar;C:\Users\admin\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.17.1\log4j-to-slf4j-2.17.1.jar;C:\Users\admin\.m2\repository\org\apache\logging\log4j\log4j-api\2.17.1\log4j-api-2.17.1.jar;C:\Users\admin\.m2\repository\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;C:\Users\admin\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\admin\.m2\repository\org\springframework\spring-core\5.3.16\spring-core-5.3.16.jar;C:\Users\admin\.m2\repository\org\springframework\spring-jcl\5.3.16\spring-jcl-5.3.16.jar;C:\Users\admin\.m2\repository\org\yaml\snakeyaml\1.29\snakeyaml-1.29.jar;C:\Users\admin\.m2\repository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.6.4\spring-boot-starter-web-2.6.4.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.6.4\spring-boot-starter-json-2.6.4.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.13.1\jackson-databind-2.13.1.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.13.1\jackson-annotations-2.13.1.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.13.1\jackson-core-2.13.1.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.1\jackson-datatype-jdk8-2.13.1.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.1\jackson-datatype-jsr310-2.13.1.jar;C:\Users\admin\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.1\jackson-module-parameter-names-2.13.1.jar;C:\Users\admin\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.6.4\spring-boot-starter-tomcat-2.6.4.jar;C:\Users\admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.58\tomcat-embed-core-9.0.58.jar;C:\Users\admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.58\tomcat-embed-el-9.0.58.jar;C:\Users\admin\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.58\tomcat-embed-websocket-9.0.58.jar;C:\Users\admin\.m2\repository\org\springframework\spring-web\5.3.16\spring-web-5.3.16.jar;C:\Users\admin\.m2\repository\org\springframework\spring-beans\5.3.16\spring-beans-5.3.16.jar;C:\Users\admin\.m2\repository\org\springframework\spring-webmvc\5.3.16\spring-webmvc-5.3.16.jar;C:\Users\admin\.m2\repository\org\springframework\spring-aop\5.3.16\spring-aop-5.3.16.jar;C:\Users\admin\.m2\repository\org\springframework\spring-expression\5.3.16\spring-expression-5.3.16.jar;C:\Users\admin\.m2\repository\org\projectlombok\lombok\1.18.22\lombok-1.18.22.jar;C:\Users\admin\.m2\repository\org\eclipse\paho\org.eclipse.paho.client.mqttv3\1.2.5\org.eclipse.paho.client.mqttv3-1.2.5.jar" com.example.mqtt.MqttApplication
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.4)
2023-11-09 16:04:49.995 INFO 24532 --- [ main] com.example.mqtt.MqttApplication : Starting MqttApplication using Java 1.8.0_161 on DESKTOP-ITTFGNT with PID 24532 (D:\project\mqtt\target\classes started by admin in D:\project\mqtt)
2023-11-09 16:04:49.998 INFO 24532 --- [ main] com.example.mqtt.MqttApplication : The following 1 profile is active: "dev"
2023-11-09 16:04:50.939 INFO 24532 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8089 (http)
2023-11-09 16:04:50.948 INFO 24532 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-11-09 16:04:50.948 INFO 24532 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.58]
2023-11-09 16:04:51.031 INFO 24532 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-11-09 16:04:51.031 INFO 24532 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 989 ms
2023-11-09 16:04:51.466 INFO 24532 --- [ main] c.e.mqtt.factory.MqttClientFactory : mqtt连接成功!!!
2023-11-09 16:04:51.477 INFO 24532 --- [ main] c.e.mqtt.controller.BaseMqttController : 批量订阅成功---------
2023-11-09 16:04:51.478 INFO 24532 --- [63-43ab0c0210c2] c.e.mqtt.controller.BaseMqttController : 接收到消息topic1我是topic1,发送了一条MQTT的消息2023-11-09 16:04:35
2023-11-09 16:04:51.480 INFO 24532 --- [63-43ab0c0210c2] c.e.mqtt.controller.BaseMqttController : 接收到消息topic2我是topic2,发送了一条MQTT的消息2023-11-09 16:04:35
2023-11-09 16:04:51.480 INFO 24532 --- [63-43ab0c0210c2] c.e.mqtt.controller.BaseMqttController : 接收到消息topic3我是topic3,发送了一条MQTT的消息2023-11-09 16:04:35
2023-11-09 16:04:51.733 INFO 24532 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8089 (http) with context path ''
2023-11-09 16:04:51.741 INFO 24532 --- [ main] com.example.mqtt.MqttApplication : Started MqttApplication in 2.267 seconds (JVM running for 3.293)