RabbitMq Android接收端 断网数据完整

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。其中较为成熟的MQ产品有IBM WEBSPHERE MQ等等。
RabbitMQ 内部结构
1.  Message
消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
2.  Publisher
消息的生产者,也是一个向交换器发布消息的客户端应用程序。
3.  Exchange
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
4.  Binding
绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
5.  Queue
消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
6.  Connection
网络连接,比如一个TCP连接。
7.  Channel
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
8.  Consumer
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
9.  Virtual Host
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。
10. Broker
表示消息队列服务器实体。
引入
implementation 'com.rabbitmq:amqp-client:4.0.0'

//arr的封装
package com.fszn.rabbitmqarr;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * 类    名:   RabbitMQArr
 * 创 建 者:   张华
 * 创建时间:   2018/7/4 15:28
 * 描    述:
 * Exchange:交换机,决定了消息路由规则;
 * Queue:消息队列;
 * Channel:进行消息读写的通道;
 * Bind:绑定了Queue和Exchange,意即为符合什么样路由规则的消息,将会放置入哪一个消息队列;
 * <p>
 * 因为你发送消息的时候,需要指定  交换机的名称 和 路由键名称;
 * 而F创建的队列需要通过路由键和交换机进行绑定,
 * 那么你Android端发布的消息就会发送到F创建的队列中(你的交换机名称和路由键肯定要和F创建的队列相关联的交换机名称和路由键相同。)
 * <p>
 * 交换机的名称 : TestRabbitmq.Message:TestRabbitmq
 * 路由键 :  ftf
 * 队列名称:
 * <p>
 * http://www.rabbitmq.com/tutorials/tutorial-one-java.html
 * https://my.oschina.net/xiaozhutefannao/blog/1838876
 */
public class RabbitMQArr extends AppCompatActivity {
    private static final String TAG = "RabbitMQArr";
    private ConnectionFactory factory;
    private Connection connection = null;
    private Channel    channel    = null;

    public RabbitMQArr(String host, int port, String username, String password, String virtualHostname) {
        factory = new ConnectionFactory();
        setUpConnectionFactory(host, port, username, password, virtualHostname);// 连接设置
    }

    private void setUpConnectionFactory(String host, int port, String username, String password, String virtualHostname) {
        factory.setHost(host);//主机地址:192.168.8.23
        factory.setPort(port);// 端口号:5672
        factory.setUsername(username);// 用户名 admin
        factory.setPassword(password);// 密码  123456
        factory.setVirtualHost(virtualHostname);
        factory.setAutomaticRecoveryEnabled(true);//设置网络异常重连
        factory.setRequestedHeartbeat(1);//是否断网
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate()");
    }

    /***
     *  发布信息
     * @param exchangeName   交换机名称
     * @param routingKey     路由键 关键字
     * @param msg             发布的信息
     */
    public void publishMessage(String exchangeName, String routingKey, String msg) {
        publishToAMPQ(exchangeName, routingKey);
        publishMessage(msg);
    }


    /**
     * 接收信息
     *
     * @param queueName    队列名称
     * @param exchangeName 交换机名称
     * @param routingKey   路由  关键字
     */
    Thread subscribeThread; //用于从线程中获取数据,更新ui

    public void subscribe(final Handler handler, final String queueName, final String exchangeName, final String routingKey, final String exchangeType) {
        subscribeThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Log.d("subscribe", "111111111111111111111");
                        if (connection == null) {
                            connection = factory.newConnection();  //使用之前的设置,建立连接
                            Log.d("subscribe", "22222222222222222222222" + connection);
                        }
                        Log.d("subscribe", "========================================");
                        //创建一个通道
                        channel = connection.createChannel(2);
                        Log.d("subscribe", "33333333333333333333333333" + channel);
                        //这里的创建队列,是为了防止 消费 在 生产 之前
                        channel.queueDeclare(queueName, true, false, false, null);
                        Log.d("subscribe", "444444444444444444444444444");
                        //绑定队列
                        channel.exchangeDeclare(exchangeName, exchangeType, true, false, null);
                        Log.d("subscribe", "55555555555555555555555555555");
                        //绑定队列
                        channel.queueBind(queueName, exchangeName, routingKey, null);
                        Log.d("subscribe", "666666666666666666666666666666");
                        //创建消费者
                        QueueingConsumer consumer = new QueueingConsumer(channel);
                        Log.d("subscribe", "7777777777777777777777777777777" + consumer);
                        //一次只发送一个,处理完成一个再获取下一个
                        channel.basicQos(1);
                        Log.d("subscribe", "8888888888888888888888888888888888");
                        //将队列绑定到消息交换机exchange上
                        channel.basicConsume(queueName, false, consumer);
                        Log.d("subscribe", "99999999999999999999999999999999999999999");
                        //channel.basicNack(1000, false, false);
                        while (true) {
                            Log.d("subscribe", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa     " + consumer);
                            //wait for the next message delivery and return it.
                            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                            Log.d("subscribe", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
                            channel.basicNack(delivery.getEnvelope().getDeliveryTag(), true, false);
                            String message = new String(delivery.getBody());
                            Log.d("subscribe", "cccccccccccccccccccccccccccccccccc");
                            //从message池中获取msg对象更高效
                            Message msg = handler.obtainMessage();
                            Bundle bundle = new Bundle();
                            bundle.putString("msg", message);
                            msg.setData(bundle);
                            handler.sendMessage(msg);
                            Log.d("subscribe", "ddddddddddddddddddddddddddddddddddddd");
                        }
                    } catch (InterruptedException e) {
                        Log.d("subscribe", "0000000000000000000000000000000000000000000");
                        break;
                    } catch (Exception e1) {
                        Log.d(TAG, "Connection broken: " + e1.getClass().getName());
                        Log.d("subscribe", "99999999999999999999999999999999999999");
                        SystemClock.sleep(5 * 1000); //sleep and then try again
                    }
                }
            }
        });
        subscribeThread.start();
    }

    /**
     * @param exchangeName 交换机名称
     * @param routingKey   路由关键字
     */
    private BlockingDeque<String> queue = new LinkedBlockingDeque<>(); // 创建内部消息队列,供消费者发布消息用
    Thread publishThread;

    public void publishToAMPQ(final String exchangeName, final String routingKey) {//Constant.MQ_ROUTINGKEY_MAP_REQUEST
        publishThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        // 创建连接
                        if (connection == null)
                            connection = factory.newConnection();
                        // 创建通道
                        if (channel == null)
                            channel = connection.createChannel();
                        channel.confirmSelect();
                        while (true) {
                            String message = queue.takeFirst();
                            try {
                                // 发布消息     exchange          routingKey
                                channel.basicPublish(exchangeName, routingKey, null, message.getBytes());
                                channel.waitForConfirmsOrDie();
                                Log.d(TAG, "发布消息..........");
                            } catch (Exception e) {
                                queue.putFirst(message);
                                throw e;
                            }
                        }
                    } catch (InterruptedException e) {
                        break;
                    } catch (Exception e) {
                        Log.d("TAG_Publish", "Connection broken: " + e.getClass().getName());
                        SystemClock.sleep(5 * 1000); //sleep and then try again
                    }
                }
            }
        });
        publishThread.start();
    }

    public void publishMessage(String message) {
        try { //向内部阻塞队列添加一条消息
            queue.putLast(message);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

        常量类:
        public class Constant {
        public static final String host            = "192.168.8.23"; //IP
        public static final int    port            = 5672;  //端口
        public static final String username        = "admin";//用户名
        public static final String password        = "123456";//密码
        public static final String exchangename    = "TestRabbitmq.Message:TestRabbitmq";  // 交换机名
        public static final String routingKey      = "ftf";  //路由 关键字
        public static final String queuename       = "TestRabbitmq.Message:TestRabbitmq_ftf"; //队列名
        public static final String exchangeType    = "topic";// exchange type  :  fanout、direct、topic、headers
        public static final String virtualHostname = "/";  //虚拟机名
    }
    使用
     mRabbitMQArr = new RabbitMQArr(Constant.host, Constant.port, Constant.username, Constant.password,Constant.virtualHostname);
     mRabbitMQArr.subscribe(mHandler, Constant.queuename, Constant.exchangename, Constant.routingKey, Constant.exchangeType);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值