1、MQTT服务器环境准备:
由于工作中有用到MQTT,所以不用搭建MQTT服务器,但是那是生产环境,不能随便搞,所以,只能白嫖。 点击这里试用14天。这个链接点进去,点击免费试用,按指引来,就能一键部署一个MQTT服务器,足够学习使用。然后下载MQTT客户端MQTTX点击这里,就可以下载,然后简单看一下怎么使用,就可以先连接着玩一玩。
2、项目搭建:
2.1、目录结构:
2.2、依赖配置:
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
maven { url "https://maven.aliyun.com/nexus/content/groups/public"}
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:2.4.2'
implementation 'org.springframework.integration:spring-integration-mqtt:5.3.2.RELEASE'
}
2.3、yml配置:
mqtt:
username: test
password: test123
url: tcp://59.110.140.97:1883
clientId: ${random.value}
2.4、yml配置对应的实体
@Component
@ConfigurationProperties(prefix = "mqtt")
public class MqttProperties {
private String url;
private String username;
private String password;
private String clientId;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
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 getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
}
2.5、消费者客户端配置:
@Configuration
// 开启对Spring-Integration组件的扫描
@IntegrationComponentScan
/**
* mqtt消费端配置
*/
public class MqttConsumerConfiguration {
@Resource
private MqttProperties mqttProperties;
@Resource
private MqttInboundHandler mqttInboundHandler;
@Bean
public MessageChannel inputChannel(){
return new DirectChannel();
}
@Bean
public MqttPahoClientFactory mqttPahoClientFactory(){
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setServerURIs(new String[]{mqttProperties.getUrl()});
mqttConnectOptions.setUserName(mqttProperties.getUsername());
mqttConnectOptions.setPassword(mqttProperties.getPassword().toCharArray());
// 客户端连接服务端超时时间
mqttConnectOptions.setConnectionTimeout(10);
// 从消息发送到消息接收的时间间隔,超过视为断连
mqttConnectOptions.setKeepAliveInterval(90);
// 断连是是否清除会话
mqttConnectOptions.setCleanSession(true);
// 断线重连
mqttConnectOptions.setAutomaticReconnect(true);
DefaultMqttPahoClientFactory clientFactory = new DefaultMqttPahoClientFactory();
clientFactory.setConnectionOptions(mqttConnectOptions);
return clientFactory;
}
@Bean
public MessageProducer inbound(MqttPahoClientFactory mqttPahoClientFactory){
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(
mqttProperties.getClientId(), mqttPahoClientFactory, "hello/#");
/**
* By default, the default DefaultPahoMessageConverter produces a message with a String payload with the following headers:
* mqtt_topic: The topic from which the message was received
* mqtt_duplicate: true if the message is a duplicate
* mqtt_qos: The quality of service
*/
adapter.setConverter(new DefaultPahoMessageConverter());
// 服务质量:0:至多一次;1:至少一次;2:正好一次
adapter.setQos(1);
adapter.setOutputChannel(inputChannel());
return adapter;
}
@Bean
/**
* ServiceActivator是用于将服务实例连接到消息传递系统的通用端点。必须配置输入消息通道,如果要调用的服务方法能够返回值,还可以提供输出消息通道
*/
@ServiceActivator(inputChannel = "inputChannel")
public MessageHandler inBoundHandler(){
return mqttInboundHandler;
}
}
2.6、消费消息的方法:
@Component
public class MqttInboundHandler implements MessageHandler {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println(message.getPayload());
}
}
2.7、生产者客户端的配置:
@Configuration
@IntegrationComponentScan
/**
* mqtt生产端配置
*/
public class MqttProducerConfiguration {
@Resource
private MqttProperties mqttProperties;
@Bean
public MessageChannel outPutChannel(){
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel = "outPutChannel")
public MessageHandler outBound(MqttPahoClientFactory mqttPahoClientFactory){
MqttPahoMessageHandler mqttPahoMessageHandler = new MqttPahoMessageHandler(mqttProperties.getClientId(), mqttPahoClientFactory);
mqttPahoMessageHandler.setAsync(true);
return mqttPahoMessageHandler;
}
}
2.8、生产者生产消息的方法:
@Component
@MessagingGateway(defaultRequestChannel = "outPutChannel")
public interface MqttGateWay {
void sendToMqtt(String payload,@Header(MqttHeaders.TOPIC) String topic);
}
2.9、调用生产者进行消息发送:
@RestController
@RequestMapping("/say")
public class ProductMqttMessageController {
@Resource
private MqttGateWay mqttGateWay;
@GetMapping("/hello/{message}")
public void sendMqttMessage(@PathVariable("message") String message){
mqttGateWay.sendToMqtt(message,"hello");
}
}
3、运行效果
首先,我们可以在IDEA里对这个demo启动两个实例,方法如下:
3.1、第一个实例:
3.2、第二个实例:
然后分别启动:
选择要启动的应用,然后点击右侧运行的绿三角即可启动两个应用。
4、访问:
例如可以访问:http://localhost:8081/say/hello/mqtt1, 可以看到后台打印出了接收到的消息。