RabbitMQ Java简单入门开发

RabbitMQ Java简单入门开发

最近公司安排简单任务,在两套系统中做数据对接,使用到了RabbitMQ消息中间件,由于也是第一次在正式环境中使用,在网上也查询了很多资料,也有很多具体的代码,但也只知道那是别人实现,而不知道具体的实现流程,所以参照着看了一些源代码,写了一些注释:

源代码

package MessageQueue;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

public class MQTest {

    public static void main(String[] args) {

        //sendMessage();
        receiveMessage();


    }

    //消息发送
    public static void  sendMessage(){
        ConnectionFactory factory = null;
        Connection connection = null;
        Channel channel= null;
        try {
            // 创建MQ工厂类,并配置相关参数
            factory = new ConnectionFactory();
            factory.setHost("192.168.0.116");// MQip,默认为localhost
            // 鬼才知道为什么是这个端口,明明是15672,然后在MQ服务器上看到了这个端口,试了一下就通了
            factory.setPort(5673);// MQ端口,默认为5672(SSL状态下为5671)
            // 用户名和密码默认为guest和guest,如果不一致,自行设置
            // 虚拟IP默认为 /,如果不一致自行设置,这两个参数都可以在MQ服务器上找到
            // factory.setUsername("guest");
            // factory.setPassword("guset");
            // factory.setVirtualHost("/");

            // 启用断开恢复机制
            // factory.setAutomaticRecoveryEnabled(true);
            System.out.println("Virtual Host:" + factory.getVirtualHost());
            System.out.println("Username:" + factory.getUsername());
            System.out.println("Password:" + factory.getPassword());
            // 最后可能还需要设置两个参数
            // connectionTimeout,连接超时时间(表示超过该时限,建立的连接就失效了,默认为0,表示无限制)
            // handshakeTimeout,握手超时时间(表示在建立连接时,超过该时限就报timeout的异常,默认为10秒,
            // 但后续会/2,也就是说5秒没连接上就超时了)
            // 其它参数可以暂时不用关注了

            // 创建连接
            connection = factory.newConnection();
            // 创建信息通道
            channel = connection.createChannel();
            // 配置通道 SEND_DEMO: 队列名
            // 接下来三个boolean: (1)队列是否可持久化,即重启后该队列是否依然存在,
            // (2)该队列是否是独占的,即连接上来时它占用整个网络连接
            // (3)是否自动销毁,即当这个队列不再被使用的时候即没有消费者对接上来时自动删除
            // 最后一个map参数: 其它参数,如该队列的存活时间,
            // 注意的是这里也申明了队列名,接下来又申明了一次,
            // 这是因为在接收和发送之前,我们需要确保该队列名是存在的,要不然做得工作是徒劳的
            channel.queueDeclare("SEND_DEMO", true, false, false, null);
            System.out.println("通道建立成功!");

            // 通过通道发送消息,消息以字符流的形式发送
            // 第一个参数:消息发布的地方(因为在MQ服务器上,队列绑定了From exchange的)
            // 第二个参数:队列名
            // 第三个参数:参数的其它属性
            // 第四个参数:发送消息的字符流
            channel.basicPublish("", "SEND_DEMO", null, "This is a testing".getBytes());  

            System.out.println("[x] I have send the message of 'This is a testing'!");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();            
        } finally {
            try {
                if(channel != null)
                    channel.close();
                if(connection != null)
                    connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    }

    // 消息接收
    public static void receiveMessage(){
        ConnectionFactory factory = null;
        Connection connection = null;
        Channel channel = null;
        try {
            // 创建MQ工厂类,并配置相关参数
            factory = new ConnectionFactory();
            factory.setHost("192.168.0.116");// MQip
            // 鬼才知道为什么是这个端口,明明是15672,然后在MQ服务器上看到了这个端口,试了一下就通了
            factory.setPort(5673);// MQ端口
            // 用户名和密码默认为guest和guest,如果不一致,自行设置
            // 虚拟IP默认为 /,如果不一致自行设置,这两个参数都可以在MQ服务器上找到
            // factory.setUsername("guest");
            // factory.setPassword("guset");
            // factory.setVirtualHost("/");
            System.out.println("Virtual Host:" + factory.getVirtualHost());
            System.out.println("Username:" + factory.getUsername());
            System.out.println("Password:" + factory.getPassword());

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

            // 配置通道
            // 第一个参数: 队列名
            // 接下来三个boolean: (1)队列是否可持久化,即重启后该队列是否依然存在,
            // (2)该队列是否是独占的,即连接上来时它占用整个网络连接
            // (3)是否自动销毁,即当这个队列不再被使用的时候即没有消费者对接上来时自动删除
            // 最后一个map参数: 其它参数,如该队列的存活时间,
            // 注意的是这里也申明了队列名,接下来又申明了一次,
            // 这是因为在接收和发送之前,我们需要确保该队列名是存在的,要不然做得工作是徒劳的
            channel.queueDeclare("SEND_DEMO", true, false, false, null);  
            System.out.println("通道建立成功!");


            // 正式服务器上推荐使用这种方式进行数据接收,下面一种方式只适合在main方法中测试,
            // 如果使用这种方式在main方法中测试,注意在后面有句Thread.sleep(2000),
            // 因为绑定接收操作类后,在finally中将channel和connection都关闭了,
            // 此时数据还没有开始接收或者还没有接收完呢。而迁移至服务器的时候,可以单独写一个方法关闭连接
            Consumer consumer = new DefaultConsumer(channel) {

                @Override
                public void handleDelivery(String consumerTag, Envelope envelope,
                        AMQP.BasicProperties properties, byte[] body)
                        throws IOException {
                    String message = new String(body, "UTF-8");
                    System.out.println("message:" + message);
                    getChannel().basicAck(envelope.getDeliveryTag(), false);

                }

                public void handleConsumeOk(String consumerTag) {
                    System.out.println("Consumer "+consumerTag +" registered");     
                }


            };  

            channel.basicConsume("SEND_DEMO", false, consumer);
            Thread.sleep(2000);


            // QueueingConsumer consumer = new QueueingConsumer(channel);
            // 通过消息通道接收消息
            // 第一个参数: 队列名字
            // 第二个参数: 是否自动应答,如果为真,消息一旦被接收到,服务端就知道该消息已经投递,
            // 从而从队列中将消息剔除,否则,需要在接收端手工调用channel.basicAck()方法
            // 通知服务端,如果没有调用,消息将会进入unacknowledged状态,并且当消费者连接断开
            // 后变成ready状态重新进入队列(通俗来讲,就是在接收数据时,是否应答,如果没有自动
            // 应道,就需要手工的签字确认,如果都没有做,那服务器就当该消息没有被接收,会一直存在
            // 消息队列中)
            // 第三个参数: 具体消息接收类。
            // channel.basicConsume("SEND_DEMO", true, consumer); 

            // 接收消息队列里的记录
            // QueueingConsumer.Delivery delivery = null;
            //
            // while (true) {
            // delivery = consumer.nextDelivery();
            // String message = new String(delivery.getBody());
            // System.out.println("[x] I have received the message of '" + message + "'!");
            // } 


        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();            
        } finally {
            try {
                if(channel != null)
                    channel.close();
                if(connection != null)
                    connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    }

}

[1]: http://www.tuicool.com/articles/EJBrY3R RabbitMQ 连接断开处理-自动恢复
[2]: http://www.oschina.net/translate/getting-started-with-rabbitmq-in-java RabbitMQ 入门指南(Java)
[3]: http://blog.csdn.net/wangyonglin1123/article/details/24643277 Rabbitmq Java Demo详解

你可能感兴趣的:(java,rabbitmq)