-
MQTT介绍
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的轻量级协议,该协议构建于TCP/IP协议之上,MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
-
MQTT代理服务器安装
安装教程请看上一篇文章:CentOS7.0安装EMQ代理服务 -
引入所需要的jar包
<!--Spring Boot jar -->
<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.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- End -->
<!-- MQTT-jar -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.fusesource.mqtt-client</groupId>
<artifactId>mqtt-client</artifactId>
<version>1.14</version>
</dependency>
- 配置application.properties文件
#端口号
server.port=${server.prot}
spring.application.name=msmq-server
#MQTT配置信息
#MQTT-用户名
spring.mqtt.username=admin
#MQTT-密码
spring.mqtt.password=admin123
#MQTT-服务器连接地址,如果有多个,用逗号隔开,如:tcp://127.0.0.1:61613,tcp://192.168.2.133:61613
spring.mqtt.url=tcp://172.80.5.222:1883
#MQTT-连接服务器默认客户端ID
spring.mqtt.client.id=mqttId
#MQTT-消息订阅主题,实际可在调用接口时指定,如果有多个,用逗号隔开,
spring.mqtt.topic=iot/mqtt/swd/SITE
#连接超时
spring.mqtt.completionTimeout=3000
- MQTT消息订阅代码
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MqttCofigBean {
@Value("${spring.mqtt.username}")
private String username;
@Value("${spring.mqtt.password}")
private String password;
@Value("${spring.mqtt.url}")
private String hostUrl;
@Value("${spring.mqtt.client.id}")
private String clientId;
@Value("${spring.mqtt.topic}")
private String msgTopic;
@Value("${spring.mqtt.completionTimeout}")
private int completionTimeout ; //连接超时
/**
* 获取用户名
* @return
*/
public String getUsername() {
return this.username;
}
/**
* 获取密码
* @return
*/
public String getPassword() {
return this.password;
}
/**
* 获取服务器连接地址
* @return
*/
public String getHostUrl() {
return this.hostUrl;
}
/**
* 获取客户端ID
* @return
*/
public String getClientId() {
return this.clientId;
}
/**
* 获取默认主题
* @return
*/
public String[] getMsgTopic() {
String[] topic=msgTopic.split(",");
return topic;
}
/***
* 获取连接超时时间
* @return
*/
public int getCompletionTimeout() {
return this.completionTimeout;
}
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.MqttTopic;
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.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import cn.msmq.config.MqttCofigBean;
/**
* MQTT客户端订阅消息类
* @author zhongyulin
*
*/
@Component
public class MqttConsumer implements ApplicationRunner{
private static Logger logger=LoggerFactory.getLogger(MqttConsumer.class);
private static MqttClient client;
private static MqttTopic mqttTopic;
/**
* MQTT连接属性配置对象
*/
@Autowired
public MqttCofigBean mqttCofigBean;
/**
* 初始化参数配置
*/
@Override
public void run(ApplicationArguments args) throws Exception {
logger.info("初始化启动MQTT连接");
this.connect();
}
/**
* 用来连接服务器
*/
private void connect() throws Exception{
client = new MqttClient(mqttCofigBean.getHostUrl(),mqttCofigBean.getClientId(), new MemoryPersistence());
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(mqttCofigBean.getUsername());
options.setPassword(mqttCofigBean.getPassword().toCharArray());
options.setCleanSession(false); //是否清除session
// 设置超时时间
options.setConnectionTimeout(30);
// 设置会话心跳时间
options.setKeepAliveInterval(20);
try {
String[] msgtopic = mqttCofigBean.getMsgTopic();
//订阅消息
int[] qos = new int[msgtopic.length];
for (int i = 0; i < msgtopic.length; i++) {
qos[i]=0;
}
client.setCallback(new TopMsgCallback(client,options,msgtopic,qos));
client.connect(options);
client.subscribe(msgtopic,qos);
logger.info("MQTT连接成功:"+mqttCofigBean.getClientId()+":"+client);
} catch (Exception e) {
logger.error("MQTT连接异常:"+e);
}
}
/**
* 重连
* @throws Exception
*/
public void reConnect() throws Exception {
if(null != client) {
this.connect();
}
}
/**
* 订阅某个主题
* @param topic
* @param qos
*/
public void subscribe(String topic,int qos){
try {
logger.info("topic:"+topic);
client.subscribe(topic, qos);
} catch (MqttException e) {
e.printStackTrace();
}
}
public MqttClient getClient() {
return client;
}
public void setClient(MqttClient client) {
this.client = client;
}
public MqttTopic getMqttTopic() {
return mqttTopic;
}
public void setMqttTopic(MqttTopic mqttTopic) {
this.mqttTopic = mqttTopic;
}
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import cn.msmq.config.MqttConfig;
/**
* MQTT消息处理类
* @author zhongyulin
* */
public class TopMsgCallback implements MqttCallback {
private static Logger logger=LoggerFactory.getLogger(TopMsgCallback.class);
private MqttClient client;
private MqttConnectOptions options;
private String[] topic;
private int[] qos;
public TopMsgCallback() {}
public TopMsgCallback(MqttClient client, MqttConnectOptions options,String[] topic,int[] qos) {
this.client = client;
this.options = options;
this.topic=topic;
this.qos=qos;
}
/**
* 断开重连
*/
public void connectionLost(Throwable cause) {
logger.info("MQTT连接断开,发起重连");
while(true) {
try {
Thread.sleep(30000);
client.connect(options);
//订阅消息
client.subscribe(topic,qos);
logger.info("MQTT重新连接成功:"+client);
break;
} catch (Exception e) {
e.printStackTrace();
continue;
}
}
}
/**
* 接收到消息调用令牌中调用
*/
public void deliveryComplete(IMqttDeliveryToken token) {
}
/**
* 消息处理
*/
public void messageArrived(String topic, MqttMessage message) throws Exception {
System.out.println();
//订阅消息字符
String msg=new String(message.getPayload());
byte[] bymsg=getBytesFromObject(msg);
logger.info("topic:"+topic);
logger.info("msg:"+msg);
}
//对象转化为字节码
public byte[] getBytesFromObject(Serializable obj) throws Exception {
if (obj == null) {
return null;
}
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
return bo.toByteArray();
}
- 项目启动入口
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* MSMQ服务启动入口
* @author zhongyulin
*
*/
@SpringBootApplication
public class MsmqProvider {
private static Logger logger= LoggerFactory.getLogger(MsmqProvider.class);
public static void main(String[] args) {
SpringApplication.run(MsmqProvider.class, args);
logger.info("Msmq消息服务启动成功");
}
}