Rabbitmq的原生javaAPI讲解

本文详细介绍了RabbitMQ的原生API使用方法,包括关键类ConnectionFactory、Connection及Channel的功能与操作,如创建连接、声明交换器和队列、消息发送与接收等。
说明

实际生产中一般是使用springboot封装的Template等组件来操作Rabbitmq的,但是如果了解了原生的API的使用,可以更好的理解Rabbitmq的特性和对springboot封装的组件的使用原理有一定了解。

关键的类
ConnectionFactory

从字面上看是连接工厂的意思,实际上该对象就是一个连接工厂对象,主要用于创建一个连接到Rabbitmq服务器的tcp连接。

基本的方法:

ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");  //设置连接的服务器的ip
factory.setPort(5672);   //设置端口,如果使用AMQP协议进行通信的话,这里就写该协议的通信端口。
factory.setUsername("guest");  //用户名
factory.setPassword("guest");   //密码
//设置这个uri可以代替上面的设置值,协议://用户名:密码@ip:port
//factory.setUri("amqp://guest:guest@192.168.18.140:5672");
factory.setVirtualHost("/");   //设置连接的虚拟主机
//设置连接超时时间
factory.setConnectionTimeout(10000);

Connection conn = factory.newConnection();  //创建一个TCP连接。

Connection

一个与rabbitmq服务器的TCP连接对象,因为Rabbitmq为了节省连接频繁创建和销毁的资源消耗,使用了channel来进行对Rabbitmq服务器的操作。所以Connection对象不会进行对Rabbitmq服务器的操作,该操作要交给Channel对象,而Connection对象的主要目的是为了创建一个Channel对象。

Connection conn = factory.newConnection();
Channel channel = conn.createChannel();  //创建一个channel对象,用于操作服务器。
Channel channel = conn.createChannel(1);  //创建一个channel对象,并手动指定一个通道号码。上面的方法是自动为我们分配号码。范围1-2047
Optional<Channel> channel = conn.openChannel();  //创建一个channel对象,把他封装在Optional对象中。
Optional<Channel> channel = conn.openChannel(1);//创建一个channel对象,把他封装在Optional对象中。并手动指定通道号码。范围1-2047

conn.close(); //关闭连接
Channel

对Rabbitmq服务器的操作基本都在这里了。

//交换器相关操作

//对交换器的操作,挑出来的都是重载方法中最全参数的重载方法,其他都是这个方法的删减用于使用一些默认值。
//声明一个交换器,这个是重载方法中参数最全的方法了,其他重载方法是对该方法的一些删减以使用某个默认值。DeclareOk 返回值主要用于查看一些创建信息。如果声明失败返回null。
//如果交换器已经存在,那么声明的参数一定要与已存在的交换器的参数一致,否则会报错。
Exchange.DeclareOk exchangeDeclare(String exchange, //要声明的交换器名称
        BuiltinExchangeType type,  //要声明的交换器类型,BuiltinExchangeType 是一个枚举类,对交换器四种类型进行一个枚举。
        boolean durable,  //是否持久化队列
        boolean autoDelete, //是否自动删除,具体含义可以看博主的另一篇文章有讲解
        boolean internal,  //是否内部交换器
        Map<String, Object> arguments) throws IOException; //其他属性参数。


//异步创建交换器,上面的是同步等待创建成功,这个异步,参数与上面一致。
void exchangeDeclareNoWait(String exchange,
        BuiltinExchangeType type,
        boolean durable,
        boolean autoDelete,
        boolean internal,
        Map<String, Object> arguments) throws IOException;

//对交换机进行绑定交换器
Exchange.BindOk exchangeBind(String destination, //设置目标交换器名称。
					String source,  //设置源交换器名称,也就是消息先到该交换器,再路由到目标交换器。
					String routingKey, //绑定键,到时与消息的路由键进行匹配看是否路由到绑定的交换机或队列中去。
					Map<String, Object> arguments) throws IOException; //其他参数


//异步对交换机绑定交换机,参数与上面一致。
void exchangeBindNoWait(String destination, 
						String source, 
						String routingKey, 
						Map<String, Object> arguments) throws IOException;

//删除一个交换器
Exchange.DeleteOk exchangeDelete(String exchange, //要删除的交换器名称
						 boolean ifUnused //如果为true,则交换器没有被生产者使用时才可以删除,否则删除失败,另一个重载方法使用ifUnused =false为默认值
						 ) throws IOException;

//异步删除一个交换器,参数与上面方法一致。
void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException;

//对交换器与交换器进行接触绑定
Exchange.UnbindOk exchangeUnbind(String destination, //目标交换器名称
								String source,  //源交换器名称,在这边来解绑。
								 String routingKey,  //绑定键,destination、source、routingKey三者才能确定一个绑定关系。
								  Map<String, Object> arguments //其他参数
								  ) throws IOException;

//异步对交换器与交换器进行接触绑定,参数与上面一致
void exchangeUnbindNoWait(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOException;

//查看交换器是否存在,存在就正常返回,不存在就抛出异常
Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException;

//队列相关操作

//队列相关操作
//声明创建一个队列。
Queue.DeclareOk queueDeclare(String queue,  //要创建的队列名
						 boolean durable,  //是否持久化队列
						 boolean exclusive,  //是否排他队列,如果true,那么该队列只能在声明该队列的Connection下的Channel中使用,其他Connection创建的Channel不能使用,连接断开时队列自动删除
						 boolean autoDelete,//是否自动删除
                          Map<String, Object> arguments //其他参数
                          ) throws IOException;

//异步声明创建一个队列
void queueDeclareNoWait(String queue, 
						boolean durable, 
						boolean exclusive, 
						boolean autoDelete,
                            Map<String, Object> arguments) throws IOException;

//交换器绑定队列
Queue.BindOk queueBind(String queue, //要绑定的队列名
						String exchange, //要绑定的交换器名
						String routingKey, //绑定键
						Map<String, Object> arguments //其他参数
						) throws IOException;

//异步进行交换器绑定队列
void queueBindNoWait(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

//删除队列
Queue.DeleteOk queueDelete(String queue, //要删除的队列名
					boolean ifUnused,  //如果为true,则只有队列没有被消费者使用时才删除成功,如果为false,就不管有没有,直接删除。
					 boolean ifEmpty //如果为true,则只有队列为空队列时才能删除成功
					 ) throws IOException;

//异步删除队列
void queueDeleteNoWait(String queue, boolean ifUnused, boolean ifEmpty) throws IOException;

//接触交换器与队列的绑定
Queue.UnbindOk queueUnbind(String queue, //要解绑的队列名
						String exchange,  //要解绑的交换器名
						String routingKey,  //绑定键   三者才能唯一确定一个绑定
						Map<String, Object> arguments  //其他参数
						) throws IOException;

//清空队列
Queue.PurgeOk queuePurge(String queue) throws IOException;

//查看队列是否存在,存在就返回一个DeclareOk ,不存在或者该队列时排他队列并且创建者不是这个连接,就抛出异常。
 Queue.DeclareOk queueDeclarePassive(String queue) throws IOException;

Message属性参数配置:

//原生API的消息属性参数配置主要由AMQP.BasicProperties类配置

Map<String, Object> headers = new HashMap<String, Object>();
        headers.put("name", "gupao");
        headers.put("level", "top");

        Map<String, Object> headers = new HashMap<String, Object>();
        headers.put("name", "gupao");
        headers.put("level", "top");

        AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                .deliveryMode(2)   // 2代表持久化
                .contentEncoding("UTF-8")  // 编码
                .expiration("10000")  // TTL,过期时间
                .headers(headers) // 自定义属性
                .priority(5) // 优先级,默认为5,配合队列的 x-max-priority 属性使用
                .messageId(String.valueOf(UUID.randomUUID())) //消息的Id
                .appId("order-service") //消息推送的应用程序
                .contentType("application/json")  //消息的内容类型
                .replyTo("replyToQueue")  //RPC模式下的回调
                .timestamp(new Date())  //消息发送的时间
                .userId("15355153")  //一般生产者的id
                .build();

//然后在消息发布时,指定properties
channel.basicPublish("", QUEUE_NAME, properties, "aaaa".getBytes());

这里暂时就讲那么多,关于消息的生产消费有很多细节,比如事务,消息确认、回调等等等等。另外开个新章节专门讲这些问题。

下面附上一个普通的消息收发例子:

public class MyProducer {
    private final static String EXCHANGE_NAME = "SIMPLE_EXCHANGE";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        // 连接IP
        factory.setHost("192.168.18.140");
        // 连接端口
        factory.setPort(5672);

        // 用户
        factory.setUsername("guest");
        factory.setPassword("guest");

        //设置这个uri可以代替上面的设置值,协议://用户名:密码@ip:port
        //factory.setUri("amqp://guest:guest@192.168.18.140:5672");
        // 虚拟机
        factory.setVirtualHost("/");
        //设置连接超时时间
        factory.setConnectionTimeout(10000);




        // 建立连接
        Connection conn = factory.newConnection();
        // 创建消息通道
        Channel channel = conn.createChannel(1000);



        // 要发送消息
        String msg = "Hello world, Rabbit MQ";

        // String exchange 要发送到的交换器名称, String routingKey 消息的路由键, BasicProperties props 消息的额外属性, byte[] body 消息的具体内容
        channel.basicPublish(EXCHANGE_NAME, "testdemo", null, msg.getBytes());

        channel.close();
        conn.close();
    }
}

public class MyConsumer {
    private final static String EXCHANGE_NAME = "SIMPLE_EXCHANGE";
    private final static String QUEUE_NAME = "SIMPLE_QUEUE";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        // 连接IP
        factory.setHost("192.168.18.140");
        // 默认监听端口
        factory.setPort(5672);
        // 虚拟机
        factory.setVirtualHost("/");

        // 设置访问的用户
        factory.setUsername("guest");
        factory.setPassword("guest");
        // 建立连接
        Connection conn = factory.newConnection();
        // 创建消息通道
        Channel channel = conn.createChannel();




        // 声明交换机
        // String exchange 交换机名称, String type, boolean durable, boolean autoDelete, Map<String, Object> arguments
        AMQP.Exchange.DeclareOk direct = channel.exchangeDeclare(EXCHANGE_NAME, "direct", false, false, null);
        // 声明队列
        // String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" Waiting for message....");

        // 绑定队列和交换机
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"testdemo");

        // 创建消费者
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                       byte[] body) throws IOException {
                String msg = new String(body, "UTF-8");
                System.out.println("Received message : '" + msg + "'");
                System.out.println("consumerTag : " + consumerTag );
                System.out.println("deliveryTag : " + envelope.getDeliveryTag() );
            }
        };

        // 开始获取消息
        // String queue, boolean autoAck, Consumer callback
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}


如果第一次,服务器并没有队列和交换器,要先启动消费者再启动生产者,因为队列和交换器的声明都在消费者中完成,如果有了队列和交换器,哪个先启动都没关系。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值