java mqtt,springboot+mqtt 物联网连接!!

 

https://download.csdn.net/download/m0_37946870/11818301

 

单独的一个springboot mqtt 订阅与发布接口

 

mqtt是物联网协议。 中间得需要一个支持mqtt的消息服务器。  网上有很多,,我下载的是emq。 支持插件比较多。

详细可了解官网 emq

我这里使用了 emq的http 插件   校验 用户名密码 和订阅 与发布的权限 。   

 java后台——>  通过mqtt  ——>    emq消息服务器  订阅创建主题  topic 1  ,    后台接口往主题发消息

 安卓app 等其他设备   —>  通过mqtt  ——>    emq消息服务器 订阅主题 topic 1。    接到消息。

 

如何校验安卓等其他设备 连接emq 的用户名和权限呢。。

我这里使用的是 emq里的  http插件 。。此时的流程是

 

1. java后台 启动成功  ——> 2. 通过mqtt (用户和密码,订阅主题)请求 ——>    3.emq消息服务器

4.emq 服务器    配置了http请求 ——>   java后台  校验 用户名和密码,是否可用订阅主题。。

 

上面的意思是 利用后台来决定 其他设备连接emq 和订阅发布的权限。

 

1 emq的http插件

 

配置 3个接口。 校验用户名,订阅,超级管理员

   

 

emq 调用我后台的接口。

 

 

 

如果使用的是其他的mqtt服务器的话, 直接忽略emq的配置和3个接口。

只需修改其他mqtt服务器的地址 链接就可用

 

1.maven包

 <!--mqtt-->
        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

 

1. ApplicationRunnerImpl

/**
 *@Author YangJiaBin
 *Date 2019/5/27 9:56
 * 项目启动后执行启动mqtt
 **/
@Component
public class ApplicationRunnerImpl implements ApplicationRunner
{

    @Autowired
    private MqttConfiguration mqttConfiguration;


    @Override
    public void run(ApplicationArguments args) throws Exception {
        MqttPushClient mqttPushClient = new MqttPushClient();
                mqttPushClient.connect(mqttConfiguration);
    }
}

 

 

@Component
public class Mqttbean
{
   @Autowired
   private MqttConfiguration mqttConfiguration;


    @Bean("mqttPushClient")
    public MqttPushClient getMqttPushClient() {
        MqttPushClient mqttPushClient = new MqttPushClient();
//        mqttPushClient.connect(mqttConfiguration.getHost(),
//                mqttConfiguration.getClientId(), mqttConfiguration.getUsername(),
//                mqttConfiguration.getPassword(), mqttConfiguration.getTimeout(),
//                mqttConfiguration.getKeepAlive());

        return mqttPushClient;
    }

 

public class MqttPushClient
{

    private static final Logger log = LoggerFactory.getLogger(MqttPushClient.class);

    private static MqttClient client;

    public static MqttClient getClient() {
        return client;
    }

    public static void setClient(MqttClient client) {
        MqttPushClient.client = client;
    }

    private MqttConnectOptions getOption(String userName, String password, int outTime, int KeepAlive) {
        //MQTT连接设置
        MqttConnectOptions option = new MqttConnectOptions();
        //设置是否清空session,false表示服务器会保留客户端的连接记录,true表示每次连接到服务器都以新的身份连接
        option.setCleanSession(false);
        //设置连接的用户名
        option.setUserName(userName);
        //设置连接的密码
        option.setPassword(password.toCharArray());
        //设置超时时间 单位为秒
        option.setConnectionTimeout(outTime);
        //设置会话心跳时间 单位为秒 服务器会每隔(1.5*keepTime)秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
        option.setKeepAliveInterval(KeepAlive);
        //setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
        //option.setWill(topic, "close".getBytes(), 2, true);
        option.setMaxInflight(1000);
        //        try
        //        {
        //            option.setSocketFactory(SslUtil
        //                    .getSocketFactory("E:\\emq\\emqttd\\etc\\certs\\cacert.pem", "E:\\emq\\emqttd\\etc\\certs\\client-cert.pem", "E:\\emq\\emqttd\\etc\\certs\\client-key.pem", ""));
        //        }
        //        catch (Exception e)
        //        {
        //            e.printStackTrace();
        //        }

        return option;
    }

    /**
     * 连接
     */
    public void connect(MqttConfiguration mqttConfiguration){
        MqttClient client;
        try {
            client = new MqttClient(mqttConfiguration.getHost(), mqttConfiguration.getClientId(), new MemoryPersistence());
            MqttConnectOptions options = getOption(mqttConfiguration.getUsername(),mqttConfiguration.getPassword(),
                    mqttConfiguration.getTimeout(),mqttConfiguration.getKeepAlive());
            MqttPushClient.setClient(client);
            try {
                client.setCallback(new PushCallback(this,mqttConfiguration));
                if (!client.isConnected()) {
                    client.connect(options);
                    log.info("MQTT连接成功");
                    //订阅主题
                    subscribe(mqttConfiguration.getTopic(),mqttConfiguration.getQos());

                }else {//这里的逻辑是如果连接成功就重新连接
                    client.disconnect();
                    client.connect(options);
                    log.info("MQTT断连成功");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 断线重连
     * @throws Exception
     */
    public Boolean reConnect() throws Exception {
        Boolean isConnected = false;
        if(null != client) {
            client.connect();
            if(client.isConnected()){
                isConnected = true;
            }
        }
        return isConnected;
    }

    /**
     * 发布,默认qos为0,非持久化
     * @param topic
     * @param pushMessage
     */
    public void publish(String topic,String pushMessage){
        publish(0, false, topic, pushMessage);
    }

    /**
     * 发布
     * @param qos
     * @param retained
     * @param topic
     * @param pushMessage
     */
    public void publish(int qos,boolean retained,String topic,String pushMessage){
        MqttMessage message = new MqttMessage();
        message.setQos(qos);
        message.setRetained(retained);
        message.setPayload(pushMessage.getBytes());
        MqttTopic mTopic = MqttPushClient.getClient().getTopic(topic);
        if(null == mTopic){
            log.error("MQTT topic 不存在");
        }
        MqttDeliveryToken token;
        try {
            token = mTopic.publish(message);
            token.waitForCompletion();
        } catch (MqttPersistenceException e) {
            e.printStackTrace();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发布消息的服务质量(推荐为:2-确保消息到达一次。0-至多一次到达;1-至少一次到达,可能重复),
     * retained 默认:false-非持久化(是指一条消息消费完,就会被删除;持久化,消费完,还会保存在服务器中,当新的订阅者出现,继续给新订阅者消费)
     * @param topic
     * @param pushMessage
     */
    public void publish(int qos, String topic, String pushMessage){
        publish(qos, false, topic, pushMessage);
    }

    /**
     * 订阅某个主题,qos默认为0
     * @param topic
     */
    //    public void subscribe(String[] topic){
    //        subscribe(topic,);
    //    }

    /**
     * 订阅某个主题
     * @param topic
     * @param qos
     */
    public void subscribe(String[] topic,int[] qos){
        try {
            MqttPushClient.getClient().unsubscribe(topic);
            MqttPushClient.getClient().subscribe(topic, qos);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
package com.purete.webapp.config;

import com.purete.webapp.client.MqttPushClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Component
@Configuration
@ConfigurationProperties(prefix = "mqtt")
public class MqttConfiguration
{
    private String host;
    private String clientId;
    private String username;
    private String password;
    private int timeout;
    private int KeepAlive;
    private String[] topic;
    private int[] qos;

    public String getHost()
    {
        return host;
    }

    public String getClientId()
    {
        return clientId;
    }

    public String getUsername()
    {
        return username;
    }

    public String getPassword()
    {
        return password;
    }

    public int getTimeout()
    {
        return timeout;
    }

    public int getKeepAlive()
    {
        return KeepAlive;
    }

    public void setHost(String host)
    {
        this.host = host;
    }

    public void setClientId(String clientId)
    {
        this.clientId = clientId;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }

    public void setTimeout(int timeout)
    {
        this.timeout = timeout;
    }

    public void setKeepAlive(int keepAlive)
    {
        KeepAlive = keepAlive;
    }

    public String[] getTopic()
    {
        return topic;
    }

    public int[] getQos()
    {
        return qos;
    }

    public void setTopic(String[] topic)
    {
        this.topic = topic;
    }

    public void setQos(int[] qos)
    {
        this.qos = qos;
    }
}

 

 

package com.purete.webapp.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;

/**
 *@Author YangJiaBin
 *Date 2019/5/27 10:17
 **/
@Controller
@RequestMapping("/mqtt")
public class EmqAuthHttpController
{

    @RequestMapping("/auth")
    public void mqttAuth(String clientid, String username, String password, HttpServletResponse response) {
        //auth.http.auth_req.params = clientid=%c,username=%u,password=%P

        /**
         * TODO 添加认证的逻辑,控制http的返回码, 这里的用户是否存在,通常是基于数据库做的。
         * HTTP 认证/鉴权 API
         * 认证/ACL 成功,API 返回200
         * 认证/ACL 失败,API 返回4xx
         */
        //response.setStatus(401);

        response.setStatus(200);
    }



    @RequestMapping("/superuser")
    public void mqttSuperuser(String clientid, String username, HttpServletResponse response) {
        //auth.http.super_req.params = clientid=%c,username=%u

        if(username.equals("admin")){
            response.setStatus(200);
        }else{
            response.setStatus(401);
        }
    }


    @RequestMapping("/acl")
    public void mqttAcl(String access, String username, String clientid, String ipaddr, String topic, HttpServletResponse response) {
        //auth.http.acl_req.params = access=%A,username=%u,clientid=%c,ipaddr=%a,topic=%t

        String s =  access.equals("1") ?  "订阅" : "发布";
       // response.setStatus(401);
        response.setStatus(200);
    }
}
package com.purete.webapp.controller;

import com.alibaba.fastjson.JSONObject;
import com.purete.webapp.client.MqttPushClient;
import com.purete.webapp.config.MqttConfiguration;
import com.purete.webapp.sender.MqttSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;

@RestController
public class MqController
{

    @Autowired
    private MqttSender mqttSender;
    @Autowired
    private MqttPushClient mqttPushClient;

    @RequestMapping("/mqttop")
    public String mqttop(){
        String TOPIC1="test_topic1";
        String TOPIC2="test_topic2";
        String TOPIC3="test_topic3";
        String TOPIC4="test_topic4";
        String TOPIC5="test_topic5";
        String TOPIC6="test_topic6";
        int Qos1=1;
        int Qos2=1;
        int Qos3=1;
        int Qos4=1;
        int Qos5=1;
        int Qos6=1;
        String[] topics={TOPIC1,TOPIC2,TOPIC3,TOPIC4,TOPIC5,TOPIC6};
        int[] qos={Qos1,Qos2,Qos3,Qos4,Qos5,Qos6};
        mqttPushClient.subscribe(topics,qos);
        return "订阅主题";
    }



    @RequestMapping("/mqttest")
    public String mqtest(){
        String TOPIC1="test_topic1";
        String TOPIC2="test_topic2";
        String TOPIC3="test_topic3";
        String TOPIC4="test_topic4";
        String TOPIC5="test_topic5";
        String TOPIC6="test_topic6";
        String[] topics={TOPIC1,TOPIC2,TOPIC3,TOPIC4,TOPIC5,TOPIC6};

        mqttSender.send(topics[new Random().nextInt(5)], JSONObject.toJSONString("该KEYS链接指向用来签署产品代码签名密钥。在PGP链接下载从我们的主网站的"
                + "OpenPGP的兼容签名。的SHA-512链接下载从主站点SHA512校验和。请验证 下载文件的完整性。"));
        return "发送成功吗";
    }

}
 package com.purete.webapp.sender;

import com.purete.webapp.client.MqttPushClient;
import org.eclipse.paho.client.mqttv3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

 /**
  * @Author: yangjiabin
  * @Date: 2019/04/24/ 16:11
  * @Description:
  */
 @Component(value = "mqttSender")
 public class MqttSender
 {
     private static final Logger log = LoggerFactory.getLogger(PushCallback.class);


     @Async
     public void send(String queueName, String msg) {
         System.out.println("发送主题"+queueName);
         publish(2,queueName, msg);
         //                    tsubscribery {
         //              //  Thread.sleep(1000);
         //            } catch (InterruptedException e) {
         //                e.printStackTrace();
         //            }

     }


     /**
      * 发布,默认qos为0,非持久化
      * @param topic
      * @param pushMessage
      */
     public void publish(String topic,String pushMessage){
         publish(1, false, topic, pushMessage);
     }

     /**
      * 发布
      * @param qos
      * @param retained
      * @param topic
      * @param pushMessage
      */
     public void publish(int qos,boolean retained,String topic,String pushMessage){
         MqttMessage message = new MqttMessage();
         message.setQos(qos);
         message.setRetained(retained);
         message.setPayload(pushMessage.getBytes());
         MqttTopic mTopic = MqttPushClient.getClient().getTopic(topic);
         if(null == mTopic){
             log.error("MQTT topic 不存在");
         }
         MqttDeliveryToken token;
         try {
             token = mTopic.publish(message);
             token.waitForCompletion();
         } catch (MqttPersistenceException e) {
             e.printStackTrace();
         } catch (MqttException e) {
             e.printStackTrace();
         }
     }

     /**
      * 发布消息的服务质量(推荐为:2-确保消息到达一次。0-至多一次到达;1-至少一次到达,可能重复),
      * retained 默认:false-非持久化(是指一条消息消费完,就会被删除;持久化,消费完,还会保存在服务器中,当新的订阅者出现,继续给新订阅者消费)
      * @param topic
      * @param pushMessage
      */
     public void publish(int qos, String topic, String pushMessage){
         publish(qos, false, topic, pushMessage);
     }
 }
package com.purete.webapp.sender;

import com.purete.webapp.client.MqttPushClient;
import com.purete.webapp.config.MqttConfiguration;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * @Author: yangjiabin
 * @Date: 2019/04/24/ 10:11
 * @Description:
 */
public class PushCallback implements MqttCallback {

   // private RedisTemplate<String, Object> redisDao;

    private static final Logger log = LoggerFactory.getLogger(PushCallback.class);
    private MqttPushClient client;

   // private MqttPtsService mqttStpService;
 //    public PushCallback() {
 //   }
   private MqttConfiguration mqttConfiguration;

    public PushCallback(MqttPushClient client,MqttConfiguration mqttConfiguration) {
        this.client = client;
        this.mqttConfiguration = mqttConfiguration;
    }
  /*  public PushCallback(MqttPushClient client,RedisTemplate<String, Object> redisUtils,MqttPtsService mqttStpService) {
        this.client = client;
        this.redisDao = redisUtils;
        this.mqttStpService=mqttStpService;
    }*/


    @Override
    public void connectionLost(Throwable cause) {
        /** 连接丢失后,一般在这里面进行重连 **/
        if(client != null) {
            while (true) {
                try {
                    log.info("[MQTT] 连接断开,30S之后尝试重连...");
                    Thread.sleep(30000);
                    MqttPushClient mqttPushClient = new MqttPushClient();
                    mqttPushClient.connect(mqttConfiguration);
                    if(MqttPushClient.getClient().isConnected()){
                        System.out.println("重连成功");

                    }
                    break;
                } catch (Exception e) {
                    log.error("[MQTT] 连接断开,重连失败!");
                    continue;
                }
            }
        }
        //log.info(cause.getMessage());
    }


    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        //publish后会执行到这里
        log.info("pushComplete---------" + token.isComplete());
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        // subscribe后得到的消息会执行到这里面
        log.info("接收消息主题 : " + topic);
        log.info("接收消息Qos : " + message.getQos());
        log.info("接收消息内容 : " + new String(message.getPayload()));

        try {
            //            JSONObject jsonObject = JSON.parseObject(new String(message.getPayload(), "UTF-8"));
            //            MqttDataEntity mqttDataEntity=(MqttDataEntity)JSONObject.toJavaObject(jsonObject, MqttDataEntity.class);
            //            getMqttDataEntity(jsonObject);
            //            mqttStpService.handleReceiveMsg(mqttDataEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
mqtt:
  username: admin
  password: public
  host: tcp://127.0.0.1:11883
  topic[0]: test_topic
  topic[1]: test_topic1
  qos[0]: 1
  qos[1]: 1
  clientId: test
  timeout: 10
  keepAlive: 20

 

发布了15 篇原创文章 · 获赞 17 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览