Windows + mosquitto搭建MQTT与Springboot+Mqtt测试
安装
下载mosquitto软件地址:https://mosquitto.org/download/
请记住软件安装的目录,后面要找到文件夹的路径,修改一些文件。我的电脑是D:\software\mosquitto
修改mosquitto.conf配置文件,监听的port为listener 1883
是否允许匿名登录,修改为allow_anonymous true
设置账户密码文件位置,allow_anonymous 设置为ture后没什么用了
以管理员身份运行,记住一定要用管理员
创建用户和密码,这里设置admin/admin123
创建消费者:
mosquitto_sub.exe -h 127.0.0.1 -p 1883 -u admin -P admin123 -v -t sensor
创建生产者
mosquitto_pub.exe -h 127.0.0.1 -p 1883 -u admin -P admin123 -t sensor -m "消息测试"
如果上面出现异常,服务没有启动
鼠标右键点击“在终端中打开”。
执行启动命令
.\mosquitto -c .\mosquitto.conf -v
MQTTX
下载地址:https://packages.emqx.net/MQTTX/v1.8.2/MQTTX-Setup-1.8.2-x64.exe
创建MQTT客户端
创建主题
Springboot整合Mqtt
1、导入依赖包
<!-- 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、编写配置类
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import javax.annotation.Resource;
@Configuration
public class MqttConfig {
@Resource
private MqttMessageHandler messageHandler;
/**
* 1、先创建连接
*/
/**
* 创建MqttPahoClientFactory,设置MQTT Broker连接属性,如果使用SSL验证,也在这里设置。
*
* @return factory
*/
@Bean
public MqttPahoClientFactory mqttClientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
// 设置代理端的URL地址,可以是多个
options.setServerURIs(new String[]{"tcp://127.0.0.1:1883"});
factory.setConnectionOptions(options);
return factory;
}
/**
* 2、入站通道
*/
@Bean
public MessageChannel mqttInputChannel() {
return new DirectChannel();
}
/**
* 入站,配置mq,监听主题topic
*/
@Bean
public MessageProducer inbound() {
// Paho客户端消息驱动通道适配器,主要用来订阅主题
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter("consumerClient-paho",
mqttClientFactory(), "boat", "collector", "battery", "+/sensor", "demo");
adapter.setCompletionTimeout(5000);
// Paho消息转换器
DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();
// 按字节接收消息
// defaultPahoMessageConverter.setPayloadAsBytes(true);
adapter.setConverter(defaultPahoMessageConverter);
adapter.setQos(1); // 设置QoS
adapter.setOutputChannel(mqttInputChannel());
return adapter;
}
/**
* 3、消息转化,中间站
*/
@Bean
// ServiceActivator注解表明:当前方法用于处理MQTT消息,inputChannel参数指定了用于消费消息的channel。
@ServiceActivator(inputChannel = "mqttInputChannel")
public MessageHandler handler() {
return message -> {
messageHandler.handleMessage(message);
};
}
/**
* 4、消息出去
*/
/**
* 出站通道
*/
@Bean
public MessageChannel mqttOutboundChannel() {
return new DirectChannel();
}
/**
* 出站
*/
@Bean
@ServiceActivator(inputChannel = "mqttOutboundChannel")
public MessageHandler outbound() {
// 发送消息和消费消息Channel可以使用相同MqttPahoClientFactory
MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler("publishClient", mqttClientFactory());
messageHandler.setAsync(true); // 如果设置成true,即异步,发送消息时将不会阻塞。
messageHandler.setDefaultTopic("command");
messageHandler.setDefaultQos(1); // 设置默认QoS
// Paho消息转换器
DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();
// defaultPahoMessageConverter.setPayloadAsBytes(true); // 发送默认按字节类型发送消息
messageHandler.setConverter(defaultPahoMessageConverter);
return messageHandler;
}
}
3、参数实体类
@Data
public class MyMessage {
/**
* 主题
*/
private String topic;
/**
* 消息
*/
private String content;
}
4、编写接口
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttGateway {
// 定义重载方法,用于消息发送
void sendToMqtt(String payload);
// 指定topic进行消息发送
void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);
}
5、编写controller
@RequestMapping("/mqtt")
@RestController
public class MqttController {
@Resource
private MqttGateway mqttGateway;
@PostMapping("/send")
public String send(@RequestBody MyMessage myMessage) {
// 发送消息到指定主题
mqttGateway.sendToMqtt(myMessage.getTopic(), myMessage.getContent());
return "send topic: " + myMessage.getTopic()+ ", message : " + myMessage.getContent();
}
}
6、配置Mqtt的主题
@AllArgsConstructor
@Getter
public enum MqttTopicEnum {
Serial_PORT("demo", "测试topic", "demoTopicHandler", DemoTopicHandler.class),
;
private String topic;
private String text;
private String topicHandlerBeanName;
private Class<? extends TopicHandler> clazz;
private static final Map<String, MqttTopicEnum> DATA_MAP;
static {
DATA_MAP = new HashMap<>();
for (MqttTopicEnum i : MqttTopicEnum.values()) {
DATA_MAP.put(i.getTopic(), i);
}
}
public static MqttTopicEnum byTopic(String topic) {
return DATA_MAP.get(topic);
}
}
7、编写处理主题的接口
public interface TopicHandler {
/**
* 处理
* @param message
*/
void handler(Message<?> message);
}
@Slf4j
@Service("demoTopicHandler")
public class DemoTopicHandler implements TopicHandler {
@Override
public void handler(Message<?> message) {
String payload = String.valueOf(message.getPayload());
log.info("handler(),串口数据接收,payload:{}", payload);
}
}
8、接收请求
Slf4j
@Component("messageHandler")
public class MqttMessageHandler implements MessageHandler {
@Override
public void handleMessage(Message<?> message) {
String topic = message.getHeaders().get("mqtt_receivedTopic").toString();
log.info("handleMessage(),消息处理,topic:{}", topic);
MqttTopicEnum mqttTopicEnum = MqttTopicEnum.byTopic(topic);
if (null == mqttTopicEnum) {
log.warn("handleMessage(),消息处理,warnMsg:topic消费未定义,不处理");
return;
}
TopicHandler topicHandler = SpringUtil.getBean(mqttTopicEnum.getTopicHandlerBeanName(), TopicHandler.class);
if (null == topicHandler) {
log.warn("handleMessage(),消息处理,warnMsg:topicHandler未实现");
return;
}
// topic消费处理
topicHandler.handler(message);
}
}
发送请求测试