1、安装emqttd:
Linux下用EMQ通用包安装EMQ:参考:https://www.shangmayuan.com/a/4fd1eee84fd64ca1a46c4617.html
2、添加emq的pom依赖:
<!--emqttd 相关依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-integration</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-stream</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> </dependency>
3、yml文件中的配置:
# emqttd配置 emqttd: # 账号 username: admin # 密码 password: admin # emqttd的连接地址 host-url: tcp://127.0.0.1:1883 # 客户端Id(唯一) client-id: xxxx # 默认主题 default-topic: admin # 超时时间 timeout: 30000 # 会话心跳时间 keepalive: 100
4、代码部分:
1) 配置类:
package com.eaa.common.emq.config; import com.eaa.common.emq.MqttPushClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import java.util.UUID; /** * emq的相关配置信息 * @create: 2021-11-17 */ @Component @ConfigurationProperties("spring.emqttd") public class MqttdConfig { @Autowired private MqttPushClient mqttPushClient; /** * 用户名 */ private static String username; /** * 密码 */ private static String password; /** * 连接地址 */ private static String hostUrl; /** * 客户Id */ private static String clientId; /** * 默认连接话题 */ private static String defaultTopic; /** * 超时时间 */ private static Integer timeout; /** *会话心跳时间
*/ private static Integer keepalive; public static String getUsername() { return username; } public void setUsername(String username) { MqttdConfig.username = username; } public static String getPassword() { return password; } public void setPassword(String password) { MqttdConfig.password = password; } public static String getHostUrl() { return hostUrl; } public void setHostUrl(String hostUrl) { MqttdConfig.hostUrl = hostUrl; } public static String getClientId() { return clientId; } public void setClientId(String clientId) { MqttdConfig.clientId = clientId; } public static String getDefaultTopic() { return defaultTopic; } public void setDefaultTopic(String defaultTopic) { MqttdConfig.defaultTopic = defaultTopic; } public static Integer getTimeout() { return timeout; } public void setTimeout(Integer timeout) { MqttdConfig.timeout = timeout; } public static Integer getKeepalive() { return keepalive; } public void setKeepalive(Integer keepalive) { MqttdConfig.keepalive = keepalive; } @Bean public MqttPushClient getMqttPushClient() {
// 此处的UUID.randomUUID().toString()指的就是客户端Id,若要指单个的就取上面的clientId mqttPushClient.connect(hostUrl, UUID.randomUUID().toString(), username, password, timeout, keepalive); // 以#结尾表示订阅所有以admin开头的主题 mqttPushClient.subscribe("admin/#", 0); return mqttPushClient; } }
2) 生产类:
package com.eaa.common.emq; import org.eclipse.paho.client.mqttv3.*; 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.stereotype.Component; import java.nio.charset.StandardCharsets; /** * mqttd 推送客户端(生产类) * @create: 2021-11-17 */ @Component public class MqttPushClient { private static final Logger log = LoggerFactory.getLogger(MqttPushClient.class); @Autowired private PushCallback pushCallback; private static MqttClient client; public static MqttClient getClient() { return client; } public static void setClient(MqttClient client) { MqttPushClient.client = client; } /** * 客户端连接 * @param host 连接 * @param clientId 客户端Id * @param username 用户名 * @param password 密码 * @param timeout 超时时间 * @param keepalive 保留数 */ 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); options.setAutomaticReconnect(true); // 自动重连 MqttPushClient.setClient(client); client.setCallback(pushCallback); client.connect(options); } catch (MqttException e) { log.error("连接失败......."); e.printStackTrace(); } } /** * 发布消息 * @param qos 连接方式 * @param retained 是否保留消息 * @param topic 主题 * @param pushMessage 消息体 */ public boolean publish(int qos, boolean retained, String topic, String pushMessage){ MqttMessage message = new MqttMessage(); message.setQos(qos); message.setRetained(retained); message.setPayload(pushMessage.getBytes(StandardCharsets.UTF_8)); MqttTopic mqttTopic = MqttPushClient.getClient().getTopic(topic); if (null == mqttTopic){ log.error("topic: "+ topic +"not exist!"); } MqttDeliveryToken token; try { token = mqttTopic.publish(message); token.waitForCompletion();
log.info("MQTT推送消息成功,message is:[{}]",message); } catch (MqttException e) { log.error("发布失败....",e); return false; } return true; } /** * 订阅某个主题 * @param topic 主题 * @param qos 连接方式 */ public void subscribe(String topic, int qos){ // log.info("开始订阅主题:" + topic); try { MqttPushClient.getClient().subscribe(topic, qos); } catch (MqttException e) { log.error("订阅失败....", e.getMessage()); } } }
3) 消费类:
package com.eaa.common.emq; import com.eaa.common.emq.config.MqttdConfig; 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.MqttMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 消费监听类(订阅之后执行) * @create: 2021-11-17 */ @Component public class PushCallback implements MqttCallback { private static final Logger log = LoggerFactory.getLogger(PushCallback.class); @Autowired private MqttdConfig mqttdConfig; private static MqttClient client; @Override public void connectionLost(Throwable throwable) { if (client == null || !client.isConnected()){ //mqttdConfig.getMqttPushClient(); } } @Override public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { // subscribe(订阅)后得到的消息会执行到这里面 log.info("接收消息主题:" + topic); log.info("接收消息Qos:" + mqttMessage.getQos()); log.info("接收消息内容:" + new String(mqttMessage.getPayload(), "utf-8")); } @Override public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { log.info("deliverComplete---" + iMqttDeliveryToken.isComplete()); } }
4)测试代码:
package com.shdz.web.controller.tool; import com.shdz.common.core.domain.AjaxResult; import com.shdz.emqttd.MqttPushClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * 测试Emqttd * @create: 2021-11-17 */ @Controller public class TestEmqttdController { @Autowired private MqttPushClient mqttPushClient; @PostMapping("/senMsgToMqtt") @ResponseBody public AjaxResult senMsgToMqtt(String msg){ mqttPushClient.publish(2, true, "admin/admin", msg); return AjaxResult.success(); } }
5、测试:
1)请求测试(postman):
2)emqttd控制面板模拟
6、一些资料:
- 关于emqtt使用的一些心得: https://blog.csdn.net/qq_29261497/article/details/52954749
-
emqtt使用心得: https://lostphp.com/blog/933.html