文章标题

来源:互联网 发布:sql数据库培训多少钱 编辑:程序博客网 时间:2024/06/05 03:08

RabbitMQ topic主题的例子包含线程

==

我参考网上的资料做了两个接收者和一个生产者,总共有两个项目。接收者里指定要接收的信息:如1.#和2.#,生产者随意发送信息,只有1和2开头的路由器关键字会被接收其他的不行。

发往主题类型的转发器的消息不能随意的设置选择键(routing_key),必须是由点隔开的一系列的标识符组成。标识符可以是任何东西,但是一般都与消息的某些特性相关。绑定键和选择键的形式一样。主题类型的转发器背后的逻辑和直接类型的转发器很类似:一个附带特殊的选择键将会被转发到绑定键与之匹配的队列中。

RabbitMQ中消息传递模型的核心思想是:生产者不直接发送消息到队列。实际的运行环境中,生产者是不知道消息会发送到那个队列上,她只会将消息发送到一个交换器,交换器也像一个生产线,她一边接收生产者发来的消息,另外一边则根据交换规则,将消息放到队列中。交换器必须知道她所接收的消息是什么?它应该被放到那个队列中?它应该被添加到多个队列吗?还是应该丢弃?这些规则都是按照交换器的规则来确定的。

参考了以下两个例子:

http://blog.csdn.net/lmj623565791/article/details/37706355
https://www.cloudamqp.com/blog/2015-07-29-rabbitmq-on-android.html
https://github.com/cloudamqp/android-example

首先先看生产者的模块:

我们创建一个生产者线程。生产者仅能将消息发送到一个交易所。一个交易所是一个非常简单的事物。 在它的一遍,它从生产者那里接收消息,另一边将消息推送到队列中。 这个交换所必须清楚的知道它所接收到的消息要如何处理。是否将它附加到一个特别的队列中? 是否将它附加到多个队列中?或者是否它应该被丢弃。规则的定义是由交换类型决定的。

我们创建一个服务器的连接:这里我们连接到本地机器上的代理,因此它是localhost。如果我们想连接到不同机器上的代理,只需要说明它的主机名和IP地址。

    ConnectionFactory factory = new ConnectionFactory();    private void setupConnectionFactory(){        factory.setHost("localhost");        factory.setPort(5672);        factory.setUsername("test");        factory.setPassword("test123");    }

接着我们获取到连接connection 以及mq通道channel

Connection connection = factory.newConnection();Channel channel = connection.createChannel();

RabbitMQ消息模型的核心理念是生产者永远不会直接发送任何消息给队列,一般的情况生产者甚至不知道消息应该发送到哪些队列。
相反的,生产者只能发送消息给转发器(Exchange)。转发器是非常简单的,一边接收从生产者发来的消息,另一边把消息推送到队列中。转发器必须清楚的知道消息如何处理它收到的每一条消息。是否应该追加到一个指定的队列?是否应该追加到多个队列?或者是否应该丢弃?这些规则通过转发器的类型进行定义。

接着创建一个这种类型的交易所exchange.我们必须声明一个发送队列,然后我们把消息发送到这个队列上这里是topic(主题)用来匹配的转发器类型

channel.exchangeDeclare(EXCHANGE_NAME,"topic");

既然有了转发器类型接下来就要输入信息还有转发器关键字了,因为消息内容message 是二进制数组,所以你可以随你喜好编码,队列通过路由关键字routing_key绑定。其中takeFirst检索并移除此队列的第一个元素,如果有必要,直到一个元素可用等。

String message = queue.takeFirst();String routing_key = queue2.takeFirst();

然后开始发送信息,我们用下面的语句。其中第一个参数是交易所的名字。如果是空字符串说明它是默认的或者匿名的交易所:第二个路由关键字存在的话,消息通过路由关键字的名字路由到特定的队列上。如:(发送者1.abc接收者就要1.#)或者(两者一样发送者q接收者就q)。

channel.basicPublish(EXCHANGE_NAME,routing_key,null,message.getBytes());

这就是生产的部分,以下完整的生产者代码

package com.example.dong24;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.BlockingDeque;import java.util.concurrent.LinkedBlockingDeque;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //服务器的连接:        setupConnectionFactory();        setupPubButton();        //用于从线程中获取数据,更新ui        final Handler incomingMessageHandler = new Handler(){            @Override            public void handleMessage(Message msg){                String message = msg.getData().getString("msg");                String message2 = msg.getData().getString("msg2");                TextView tv = (TextView)findViewById(R.id.textView);                TextView tv2 = (TextView)findViewById(R.id.textView2);                Date now = new Date();                SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");                tv.append(ft.format(now) + ' ' + message + "\n");                tv2.append(ft.format(now) + ' ' +message2 + "\n");                Log.i("test","msg  " + message);            }        };        //开启发送消息的生产者线程        publishToAMQP(incomingMessageHandler);    }    void setupPubButton(){        Button button = (Button)findViewById(R.id.publish);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                EditText et = (EditText)findViewById(R.id.text);                publishMessage(et.getText().toString());                et.setText("");            }        });        Button button2 = (Button)findViewById(R.id.publish2);        button2.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                EditText et = (EditText)findViewById(R.id.text2);                publishMessage2(et.getText().toString());                et.setText("");            }        });    }    Thread publishThread;    @Override    protected void onDestroy(){        super.onDestroy();        publishThread.interrupt();    }    private BlockingDeque<String> queue = new LinkedBlockingDeque<String>();    void publishMessage(String message){        try{            Log.d("","[q] " + message);            //putLast在这个队列的末尾插入指定元素,如果空间成为提供必要的等待。            queue.putLast(message);        }catch (InterruptedException e){            e.printStackTrace();        }    }    private  BlockingDeque<String> queue2 = new LinkedBlockingDeque<String>();    void publishMessage2(String message) {        try {            Log.d("", "[q ] " + queue2);            queue2.putLast(message);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    /**     * 连接设置,我们创建一个服务器的连接:     */    //抽象的socket连接,注意协议版本的处理以及授权,诸如此类的事情。    //这里我们连接到本地机器上的代理,因此它是localhost。如果我们想连接到不同机器上的代理,只需要说明它的主机名和IP地址。    ConnectionFactory factory = new ConnectionFactory();    private void setupConnectionFactory(){        factory.setHost("192.168.X.XXX");//可以用自己的IP地址        factory.setPort(5672);        factory.setUsername("test");        factory.setPassword("test123");    }    /**     * 生产者线程     */    //  生产者仅能将消息发送到一个交易所。一个交易所是一个非常简单的事物。    // 在它的一遍,它从生产者那里接收消息,另一边将消息推送到队列中。    // 这个交换所必须清楚的知道它所接收到的消息要如何处理。是否将它附加到一个特别的队列中?    // 是否将它附加到多个队列中?或者是否它应该被丢弃。规则的定义是由交换类型决定的。     void publishToAMQP(final Handler handler){        publishThread = new Thread(new Runnable() {            private static final String EXCHANGE_NAME = "topic_logs";            @Override            public void run() {                while(true){                    try{                        // 获取到连接以及mq通道                        Connection connection = factory.newConnection();                        Channel channel = connection.createChannel();                        channel.confirmSelect();                        //创建一个这种类型的交易所.我们必须声明一个发送队列,然后我们把消息发送到这个队列上                        channel.exchangeDeclare(EXCHANGE_NAME,"topic");                        while (true){                            //输入关键字                            // 声明一个队列是幂等的,仅仅在要声明的队列不存在时才创建。消息内容是二进制数组,所以你可以随你喜好编码。                            //takeFirst检索并移除此队列的第一个元素,如果有必要,直到一个元素可用等。                            String message = queue.takeFirst();                            String routing_key = queue2.takeFirst();                            try{//这第一个参数是交易所的名字。空字符串说明它是默认的或者匿名的交易所:路由关键字存在的话,消息通过路由关键字的名字路由到特定的队列上。                                                    channel.basicPublish(EXCHANGE_NAME,routing_key,null,message.getBytes());System.out.println(" [x] Sent routingKey = " + routing_key + " ,msg = " + message + ".");                                Log.d("","[s] "+message);                                channel.waitForConfirmsOrDie();                                //从message池中获取msg对象更高效                                //对于Message对象,一般并不推荐直接使用它的构造方法得到,而是建议通过使用Message.obtain()这个静态的方法或者 Handler.obtainMessage()获取。                                // Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的, 才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。                                //并不需要担心消息池中的消息过多,它是有上限的,上限为10个。 Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是 调用的Message.obtain()。                                Message msg = handler.obtainMessage();                                Message msg2 = handler.obtainMessage();                                Bundle bundle = new Bundle();                                bundle.putString("msg", message);                                bundle.putString("msg2", routing_key);                                msg.setData(bundle);                                msg2.setData(bundle);                                handler.sendMessage(msg);                            }catch (Exception e){                                Log.d("","[f] " + message);                                //putFirst在这个队列的前面插入指定元素,如果空间成为提供必要的等待。                                queue.putFirst(message);                                queue2.putFirst(routing_key);                                throw e;                            }                        }                    }catch (InterruptedException e){                        break;                    }catch (Exception e){                        Log.d("","Connection broken:" + e.getClass().getName());                        try{                            Thread.sleep(5000);                        }catch (InterruptedException e1){                            break;                        }                    }                }            }        });        publishThread.start();    }}

然后再看消费者的模块:

跟创建发送者相同,我们打开一个连接和一个通道,声明一个我们要消息的队列。注意要与发送的队列相匹配。

ConnectionFactory factory = new ConnectionFactory();        factory.setHost("localhost");        factory.setPort(5672);        factory.setUsername("test");        factory.setPassword("test123");Connection connection = factory.newConnection();Channel channel = connection.createChannel();

接着声明转发器类型,我们把消息发送到这个队列上这里是topic(主题)用来匹配的转发器类型

channel.exchangeDeclare(EXCHANGE_NAME,"topic");

我们都为队列指定了一个特定的名称。能够为队列命名对我们来说是很关键的,我们需要指定消费者为某个队列。当我们希望在生产者和消费者间共享队列时,为队列命名是很重要的。
不过,对于我们的日志系统我们并不关心队列的名称。我们想要接收到所有的消息,而且我们也只对当前正在传递的数据的感兴趣。为了满足我们的需求,需要做两件事:第一, 无论什么时间连接到Rabbit我们都需要一个新的空的队列。为了实现,我们可以使用随机数创建队列,或者更好的,让服务器给我们提供一个随机的名称。第二, 一旦消费者与Rabbit断开,消费者所接收的那个队列应该被自动删除。Java中我们可以使用queueDeclare()方法,不传递任何参数,来创建一个非持久的、唯一的、自动删除的队列且队列名称由服务器随机产生。

我们再创建队列,队列名中包含一个随机队列名。使用无参数调queueDeclare()方法,我们创建一个自动产生的名字,不持久化,独占的,自动删除的队列。例如名字像amq.gen-JzTY20BRgKO-HjmUJj0wLg。

String queueName = channel.queueDeclare().getQueue();

然后输入信息还有转发器关键字了,队列通过路由关键字routing_key绑定。要与发送者的关键字保持一致。如:(发送者1.abc接收者就要1.#)或者(两者一样发送者q接收者就q)。其中takeFirst检索并移除此队列的第一个元素,如果有必要,直到一个元素可用等。

String routing_key = queue3.takeFirst();

之后是绑定,我们需要告诉交易所发送消息给我们的队列上。这交易所和队列之间的关系称之为一个绑定。接收所有routingKey相关的消息,将队列绑定到消息交换机exchange上。一个绑定是一个交换所和一个队列之间的关系。这个很容易理解为:这个队列是对这交易所的消息感兴趣。

绑定可以附带一个额外的参数routingKey。为了与避免basicPublish方法(发布消息的方法)的参数混淆,我们准备把它称作绑定键(binding key)。

 channel.queueBind(queueName,EXCHANGE_NAME,routing_key);

注意我们在这里同样声明了一个队列。以为我们可能在发送者之前启动接收者,在我们从中获取消息之前我们想要确定这队列是否真实存在。 我们通知服务器通过此队列给我们发送消息。因此服务器会异步的给我们推送消息,在这里我们提供一个回调对象用来缓存消息, 直到我们准备好再使用它们。这就是QueueingConsumer所做的事。

QueueingConsumer consumer = new QueueingConsumer(channel);

监听队列,自动返回完成 false手动

 channel.basicConsume(queueName,true,consumer);

最后获取消息,如果没有消息,这一步将会一直阻塞,开启nextDelivery阻塞方法(内部实现其实是阻塞队列的take方法)

QueueingConsumer.Delivery delivery = consumer.nextDelivery();String message = new String(delivery.getBody());routing_key = delivery.getEnvelope().getRoutingKey();

这就是消费的部分,以下完整的消费者代码

package com.example.dong25;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.QueueingConsumer;import java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.BlockingDeque;import java.util.concurrent.LinkedBlockingDeque;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //服务器的连接:        setupConnectionFactory();        setupPubButton();        //用于从线程中获取数据,更新ui        final Handler incomingMessageHandler = new Handler(){            @Override            public void handleMessage(Message msg){                String message3 = msg.getData().getString("msg3");                String message4 = msg.getData().getString("msg4");                TextView tv3 =(TextView)findViewById(R.id.textView3);                TextView tv4 =(TextView)findViewById(R.id.textView4);                Date now = new Date();                SimpleDateFormat ft = new SimpleDateFormat("hh.mm.ss");                tv3.append(ft.format(now) + ' ' + message3 + "\n");                tv4.append(ft.format(now) + ' ' + message4 + "\n");                Log.i("test","msg3  " + message3);            }        };        //开启消费者线程   接收消息的消费者. 接收者将会输出从RabbitMQ中获取到来自发送者的消息。接收者会一直保持运行,等待消息        subscribe(incomingMessageHandler);        subscribe2(incomingMessageHandler);    }    void setupPubButton(){        Button button3 = (Button)findViewById(R.id.publish3);        button3.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                EditText et = (EditText)findViewById(R.id.text3);                publishMessage3(et.getText().toString());                et.setText("");            }        });        Button button4 = (Button)findViewById(R.id.publish4);        button4.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                EditText et = (EditText)findViewById(R.id.text4);                publishMessage4(et.getText().toString());                et.setText("");            }        });    }    Thread subscribeThread;    Thread subscribeThread2;    @Override    protected  void onDestroy(){        super.onDestroy();        subscribeThread.interrupt();        subscribeThread2.interrupt();    }    private BlockingDeque<String> queue3 = new LinkedBlockingDeque<String>();    void publishMessage3(String message){        try{            Log.d("","[q] " + message);            //putLast在这个队列的末尾插入指定元素,如果空间成为提供必要的等待。            queue3.putLast(message);        }catch (InterruptedException e){            e.printStackTrace();        }    }    private BlockingDeque<String> queue4 = new LinkedBlockingDeque<String>();    void publishMessage4(String message){        try{            Log.d("","[q] " + message);            queue4.putLast(message);        }catch (InterruptedException e){            e.printStackTrace();        }    }    /**     * 连接设置,我们创建一个服务器的连接:     */    //抽象的socket连接,注意协议版本的处理以及授权,诸如此类的事情。    //这里我们连接到本地机器上的代理,因此它是localhost。如果我们想连接到不同机器上的代理,只需要说明它的主机名和IP地址。    ConnectionFactory factory = new ConnectionFactory();    private void setupConnectionFactory(){        factory.setHost("192.168.X.XXX");//可以用自己的IP地址        factory.setPort(5672);        factory.setUsername("test");        factory.setPassword("test123");    }    /**     * 消费者线程     */    //跟创建发送者相同,我们打开一个连接和一个通道,声明一个我们要消费的队列。注意要与发送的队列相匹配。    void subscribe(final Handler handler){        subscribeThread = new Thread(new Runnable() {            private static final String EXCHANGE_NAME = "topic_logs";            @Override            public void run() {                while (true){                    try{                        //创建一个连接   创建一个频道                        Connection connection = factory.newConnection();                        Channel channel = connection.createChannel();                        //同一时刻服务器只会发一条消息给消费者 ,一次只发送一个,处理完成一个再获取下一个                        channel.basicQos(1);                        // 声明转发器                        channel.exchangeDeclare(EXCHANGE_NAME,"topic");                        // 队列名中包含一个随机队列名。使用无参数调用queueDeclare()方法,我们创建一个自动产生的名字,不持久化,独占的,自动删除的队列。                        // 队列名中包含一个随机队列名。例如名字像amq.gen-JzTY20BRgKO-HjmUJj0wLg。                        String queueName = channel.queueDeclare().getQueue();                        //输入关键字                        // 声明一个队列是幂等的,仅仅在要声明的队列不存在时才创建。消息内容是二进制数组,所以你可以随你喜好编码。                        //takeFirst检索并移除此队列的第一个元素,如果有必要,直到一个元素可用等。                        String routing_key = queue3.takeFirst();                        //我们需要告诉交易所发送消息给我们的队列上。这交易所和队列之间的关系称之为一个绑定。                        //接收所有routingKey相关的消息,将队列绑定到消息交换机exchange上                        //一个绑定是一个交换所和一个队列之间的关系。这个很容易理解为:这个队列是对这交易所的消息感兴趣。                        channel.queueBind(queueName,EXCHANGE_NAME,routing_key);                        System.out.println(" [#] Waiting for messages about routingKey. To exit press CTRL+C");                        //注意我们在这里同样声明了一个队列。以为我们可能在发送者之前启动接收者,在我们从中获取消息之前我们想要确定这队列是否真实存在。                        // 我们通知服务器通过此队列给我们发送消息。因此服务器会异步的给我们推送消息,在这里我们提供一个回调对象用来缓存消息,                        // 直到我们准备好再使用它们。这就是QueueingConsumer所做的事。                        QueueingConsumer consumer = new QueueingConsumer(channel);                        // 监听队列,自动返回完成  false手动                        channel.basicConsume(queueName,true,consumer);                        //循环获取消息                        while(true){                            //获取消息,如果没有消息,这一步将会一直阻塞,开启nextDelivery阻塞方法(内部实现其实是阻塞队列的take方法)                            QueueingConsumer.Delivery delivery = consumer.nextDelivery();                            String message = new String(delivery.getBody());                            routing_key = delivery.getEnvelope().getRoutingKey();                            System.out.println(" [x] Received routingKey = " + routing_key + ",msg = " + message + ".");                            Log.d("","[r] "+message);                            //从message池中获取msg对象更高效                            //对于Message对象,一般并不推荐直接使用它的构造方法得到,而是建议通过使用Message.obtain()这个静态的方法或者 Handler.obtainMessage()获取。                            // Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的, 才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。                            //并不需要担心消息池中的消息过多,它是有上限的,上限为10个。 Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是 调用的Message.obtain()。                            Message msg = handler.obtainMessage();                            Bundle bundle = new Bundle();                            bundle.putString("msg3",message);                            msg.setData(bundle);                            handler.sendMessage(msg);                            //putFirst在这个队列的前面插入指定元素,如果空间成为提供必要的等待。                            queue3.putFirst(routing_key);                        }                    }catch (InterruptedException e){                        break;                    }catch (Exception el){                        Log.d("","Connection broken: "+ el.getClass().getName());                        try{                            Thread.sleep(4000);                        }catch (InterruptedException e){                            break;                        }                    }                }            }        });        subscribeThread.start();    }    /**     * 消费者线程2 与1原理一样     */    void subscribe2(final Handler handler){        subscribeThread2 = new Thread(new Runnable() {            private static final String EXCHANGE_NAME = "topic_logs";            @Override            public void run() {                while (true){                    try{                        Connection connection = factory.newConnection();                        Channel channel = connection.createChannel();                        channel.basicQos(1);                        channel.exchangeDeclare(EXCHANGE_NAME,"topic");                        String queueName = channel.queueDeclare().getQueue();                        String routing_key2 = queue4.takeFirst();                        channel.queueBind(queueName,EXCHANGE_NAME,routing_key2);                        System.out.println(" [#] Waiting for messages about routingKey. To exit press CTRL+C");                        QueueingConsumer consumer = new QueueingConsumer(channel);                        channel.basicConsume(queueName,true,consumer);                        while(true){                            QueueingConsumer.Delivery delivery = consumer.nextDelivery();                            String message = new String(delivery.getBody());                            routing_key2 = delivery.getEnvelope().getRoutingKey();                            System.out.println(" [x] Received routingKey = " + routing_key2 + ",msg = " + message + ".");                            Log.d("","[r] "+message);                            Message msg2 = handler.obtainMessage();                            Bundle bundle = new Bundle();                            bundle.putString("msg4",message);                            msg2.setData(bundle);                            handler.sendMessage(msg2);                            queue4.putFirst(routing_key2);                        }                    }catch (InterruptedException e){                        break;                    }catch (Exception el){                        Log.d("","Connection broken: "+ el.getClass().getName());                        try{                            Thread.sleep(4000);                        }catch (InterruptedException e){                            break;                        }                    }                }            }        });        subscribeThread2.start();    }}

在页面方面的代码如下

这是生产者的页面

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#ffffff"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin" >    <TableLayout        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:stretchColumns="1" >        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="horizontal">            <LinearLayout                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:orientation="vertical"                android:layout_weight="1">                <EditText                    android:id="@+id/text2"                    android:layout_width="fill_parent"                    android:layout_height="50dp"                    android:background="#ffffff"                    android:hint="Enter a key"                    android:layout_weight="1"/>                <Button                    android:id="@+id/publish2"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_below="@+id/text"                    android:text="Publish routing_key"                    android:layout_weight="1"/>                <TextView                    android:id="@+id/textView2"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_below="@+id/publish"                    android:textColor="#000000"                    android:layout_weight="1"/>            </LinearLayout>        </LinearLayout>        <EditText            android:id="@+id/text"            android:layout_width="fill_parent"            android:layout_height="50dp"            android:background="#ffffff"            android:hint="Enter a message" />        <Button            android:id="@+id/publish"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_below="@+id/text"            android:text="Publish message" />        <TextView            android:id="@+id/textView"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_below="@+id/publish"            android:textColor="#000000" />    </TableLayout></ScrollView>

这是消费者的页面

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#ffffff"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin" >    <TableLayout        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:stretchColumns="1" >        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="horizontal">            <LinearLayout                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:orientation="vertical"                android:layout_weight="1">                <EditText                    android:id="@+id/text3"                    android:layout_width="fill_parent"                    android:layout_height="50dp"                    android:background="#ffffff"                    android:hint="Receive a key"                    android:layout_weight="1"/>                <Button                    android:id="@+id/publish3"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_below="@+id/text"                    android:text="Receive routing_key"                    android:layout_weight="1"/>                <TextView                    android:id="@+id/textView3"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:layout_below="@+id/publish3"                    android:textColor="#000000"                    android:layout_weight="1"/>            </LinearLayout>        </LinearLayout>        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical"            android:layout_weight="1">            <EditText                android:id="@+id/text4"                android:layout_width="fill_parent"                android:layout_height="50dp"                android:background="#ffffff"                android:hint="Receive a key"                android:layout_weight="1"/>            <Button                android:id="@+id/publish4"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_below="@+id/text"                android:text="Receive routing_key"                android:layout_weight="1"/>            <TextView                android:id="@+id/textView4"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_below="@+id/publish3"                android:textColor="#000000"                android:layout_weight="1"/>        </LinearLayout>    </TableLayout></ScrollView>

代码的部分就结束了,注意是两个项目所以要两个MainActivity,当然你自己想要合并成一个也可以。我们还要

在AndroidManifest中加入

<uses-permission android:name="android.permission.INTERNET"></uses-permission>    <uses-sdk        android:minSdkVersion="9"        android:targetSdkVersion="21" />

在build.gradle中加入—-内的内容

android {----------    packagingOptions {        exclude 'META-INF/LICENSE.txt'        exclude 'META-INF/NOTICE.txt'    }----------    }dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile 'com.android.support:appcompat-v7:25.1.0'    testCompile 'junit:junit:4.12'----------    compile 'com.rabbitmq:amqp-client:4.1.1'    compile files('libs/junit.jar')    compile files('libs/rabbitmq-client.jar')    compile files('libs/commons-cli-1.1.jar')    compile files('libs/commons-io-1.2.jar')    compile files('libs/hamcrest-core.jar')    compile files('libs/rabbitmq-client-tests.jar')----------}

以下就是源码
https://github.com/CHENRONG92/Dong23

效果如下:
模拟器的效果
run中发送和接收

原创粉丝点击