RabbitMQ(三):java API

创建链接

  • 声明连接工厂,设置host、port、username、password、VirtualHost等信息,VirtualHost默认为"/",可以不设置
ConnectionFactory factory = new ConnectionFactory();
// 自己的服务器配置
factory.setHost("192.168.0.1");
factory.setPort(5672);
factory.setUsername("admin");
factory.setPassword("admin");
factory.setVirtualHost("/");
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();

定义交换器

  • 这里声明了一个名字为user.exchange的、direct类型的、持久化的、非自动删除的队列,代码如下:
	// 成员变量声明、之后代码也会调用此处成员变量
    private static final String EXCHANGE_NAME = "user.exchange";
    private static final String USER_QUEUE = "user.queue";
    private static final String ROUTING_KEY = "direct_routingkey";
	
	channel.exchangeDeclare(EXCHANGE_NAME, "direct", true);
  • 参数详解

exchange:交换器名称

type:交换器类型

durable:是否持久化,默认否、如需请声明为true

autoDelete:是否自动删除交换器,删除条件为:autoDelete设置为true,至少有一个队列或交换器与这个交换器绑定(被使用过)、之后所有与之绑定的队列或交换器都与之解绑。并不是当与之连接的客户端都断开时,RabbitMQ自动删除本交换器。默认为否

internal:设置是否是内置交换器。如果为true,表示是内置交换器,客户端程序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器这种方式。默认非内置

arguments:其他一些结构化参数,比如 alternate-exchange,暂且不关注这个字段,传null就好

  • exchangeDeclare的重载方法。一般地,使用exchangeDeclare(String exchange, String type, boolean durable)就够了,其余参数视情况而定
    Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException;
    
    Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type) throws IOException;
    
    Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) throws IOException;
    
    Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable) throws IOException;

    Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete,
                                       Map<String, Object> arguments) throws IOException;

    Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete,
        Map<String, Object> arguments) throws IOException;

    Exchange.DeclareOk exchangeDeclare(String exchange,
                                              String type,
                                              boolean durable,
                                              boolean autoDelete,
                                              boolean internal,
                                              Map<String, Object> arguments) throws IOException;

    Exchange.DeclareOk exchangeDeclare(String exchange,
        BuiltinExchangeType type,
        boolean durable,
        boolean autoDelete,
        boolean internal,
        Map<String, Object> arguments) throws IOException;
  • exchangeDeclareNoWait方法
    exchangeDeclare与exchangeDeclareNoWait很相似,exchangeDeclareNoWait多了一个noWait参数,意思是:在服务器声明了一个exchange之后,不需要返回Declare-OK指令、exchange就可以使用,效率稍许提升,可是带来一个问题:当刚刚声明一个exchange之后(还未确认OK)、立即使用exchange就会抛出异常,因此这个方法一般不考虑。
  • exchangeDeclarePassive方法
    这个方法用来检测相应的交换器是否存在。如果存在就正常返回,如果不存在就抛出异常,同时channel也会关闭。
  • exchangeDelete方法
    删除交换器,ifUnused:true,代表如果此交换器被使用中、则删除失败。有三种实现形式,如下:
    Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException;

    void exchangeDeleteNoWait(String exchange, boolean ifUnused) throws IOException;

    Exchange.DeleteOk exchangeDelete(String exchange) throws IOException;

定义队列

  • 这里定义了一个名字为user.queue、持久化存储的、非排他的、非自动删除的队列
channel.queueDeclare(USER_QUEUE, true, false, false, null);
  • queueDeclare的重载方法不多、连带noWait方法/Passive方法一起、如下:
    Queue.DeclareOk queueDeclare() throws IOException;

    Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments) throws IOException;

    void queueDeclareNoWait(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                            Map<String, Object> arguments) throws IOException;

其中无参方法实现为:

@Override
    public com.rabbitmq.client.AMQP.Queue.DeclareOk queueDeclare()
        throws IOException
    {
        return queueDeclare("", false, true, true, null);
    }
  • 参数详解

queue:队列名称

durable:是否持久化、默认false

exclusive:是否排他、默认true。如果一个队列被声明为排他队列,该队列仅对首次声明它的链接可见,并在该connection断开连接时删除。这里需要注意三点:排他队列是基于连接( Connection) 可见的,同一个连接的不同信道 (Channel)是可以同时访问同一连接创建的排他队列; "首次"是指如果一个连接己经声明了 一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同:即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除,这种队列适用于一个客户端同时发送和读取消息的应用场景

autoDelete:是否自动删除、默认true

arguments:设置队列的其他一些参数,如 x-rnessage-ttl 、 x-expires 、x -rnax-length 、 x-rnax-length-bytes 、 x-dead-letter-exchange 、 x-deadletter-routing-key, x-rnax-priority 等

  • 删除队列
Queue.PurgeOk queuePurge(String queue) throws IOException;

队列交换器绑定

  • 如下,将队列USER_QUEUE和交换器EXCHANGE_NAME绑定,路由键为ROUTING_KEY
channel.queueBind(USER_QUEUE, EXCHANGE_NAME, ROUTING_KEY);
  • queueBind有两个重载方法
    Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException;

    Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;
  • 属性详解
    queue:队列名
    exchange:交换器名
    arguments:定义绑定的一些参数
  • queueBind还有一个noWait方法。还有解绑的两个重载方法,如下:
    void queueBindNoWait(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

    Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException;

    Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map<String, Object> arguments) throws IOException;

交换器与交换器绑定

我们不仅可以将交换器与队列绑定,也可以将交换器与交换器绑定,用法极为类似,接口如下:

    Exchange.BindOk exchangeBind(String destination, String source, String routingKey) 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.UnbindOk exchangeUnbind(String destination, String source, String routingKey) throws IOException;

    Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOException;

    void exchangeUnbindNoWait(String destination, String source, String routingKey, Map<String, Object> arguments) throws IOException;
  • 交换器绑定交换器的意义在于:多个生产者需要输出到同一个队列,供同一类型的消费者消费,多个生产者就可以通过绑定交换器、最终将消息输出到同一交换器的队列。
    交换器绑定交换器

发送消息

  • 发送消息时,指定交换器名、路由键、待序列化的数据即可,当然还有很多附加字段
// 发送对象、注意:对象必须实现Serialization接口
User user = new User();
user.setId(2);
user.setUsername("陈独秀");
user.setAge(25);
channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, null, SerializationUtils.serialize(user));

// 发送字符串
channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, null, "Hello 世界".getBytes());
  • basicPublish共有三个重载方法
    void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;

    void basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body) throws IOException;

    void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException;
  • 属性详解

exchange:交换器名称

routingKey:路由键

mandatory:当设置为true时,交换器无法根据自身的类型和路由键找到一个符合条件的队列,那么RabbitMQ会调用Basic.Return命令将消息返回给生产者。

immediate:当设置为true时,如果交换器在将消息路由到队列时发现队列上并不存在任何消费者,那么这条消息将不会存储队列中。当与路由键匹配的所有队列都没有消费者时,该消息会通过Basic.Return返回给生产者。

概括来说 , mandatory 参数告诉服务器至少将该消息路由到一个队列 中, 否则将消息返回给生产者。 immediate参数告诉服务器 , 如果该消息关联的队列上有消费者, 则 立刻投递:如果所有匹配的队列上都没有消费者,则直接将消息返还给生产者 , 不用将消息存入队列而等待消费者了。

但是RabbitMQ3.0版本开始去掉了对immediate的支持,对此RabbitMQ官网解释是:immediate参数会影响镜像队列的性能,增加了代码的复杂性,建议采用TTL和DLX的方法替代。

props:消息的基本属性集。其包含 14 个属性成员,分别有 contentType 、content Encoding 、 headers (Map<String , Object>) 、 deliveryMode 、 priority 、correlationld 、 replyTo 、 expiration 、 messageld、 timestamp 、 type 、 userld 、appld 、 clusterld

body:消息体,payload,待发送的消息主体

消费消息

RabbitMQ消费消息模式分为两种:推模式(PUSH、Basic.Consume)、拉模式(PULL、Basic.Get)。

  • 推模式
        Channel finalChannel = channel;
        channel.basicConsume(QUEUE_NAME, false, "myConsumerTag",
                new DefaultConsumer(finalChannel) {
                    @Override
                    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                        System.out.println(SerializationUtils.deserialize(body));
                        finalChannel.basicAck(envelope.getDeliveryTag(), false);
                    }
                });
        TimeUnit.SECONDS.sleep(5);

上边代码显式的将第二个参数(autoack)设置为false,表示不自动确认,然后再接受完消息体之后,通过finalChannel.basicAck(envelope.getDeliveryTag(), false);来主动确认消息。这样在主动确认消息之前、RabbitMQ不会删除消息,可以防止消息不必要的丢失。

  • basicConsumer的重载方法很多,如下:
  • 主要属性详解

queue:队列的名字

autoACK:设置为true表示自动确认,消息发出即删除

consumerTag:消费者标签,用来区分多个消费者

noLocal:设置为true表示不能将同一个Connection中生产者发送的消息传送至这个Connection的消费者

exclusive:是否排他

arguments:其他参数

callback:回调函数,上边示例代码的回调函数为:new DefaultConsumer(finalChannel)

    String basicConsume(String queue, Consumer callback) throws IOException;

    String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;

    String basicConsume(String queue, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;

    String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, Map<String, Object> arguments, Consumer callback) throws IOException;

    String basicConsume(String queue, boolean autoAck, Map<String, Object> arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, Map<String, Object> arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, Map<String, Object> arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, Consumer callback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, DeliverCallback deliverCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

    String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, DeliverCallback deliverCallback, CancelCallback cancelCallback, ConsumerShutdownSignalCallback shutdownSignalCallback) throws IOException;

对于消费者而言,重写handleDelivery()方法可以很方便的消费消息,还有几个可选重写的方法:

void handleConsumerOk(String consumerTag);

void handleCancelOk(String consumerTag);

void handleCancel(String consumerTag) throws IOExceotion;

void handleShutdownSingal(String consumerTag, ShutdownSignalException sig);

void handleRecoverOk(String consumerTag);
  • 拉模式
        GetResponse response = channel.basicGet(QUEUE_NAME, false);
        System.out.println(SerializationUtils.deserialize(response.getBody()));
        channel.basicAck(response.getEnvelope().getDeliveryTag(), false);

关闭链接

  • 先关闭channel、然后关闭connection。关闭逻辑应在finally中定义
if (channel != null) {
    try {
        channel.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        e.printStackTrace();
    }
}
if (conn != null) {
    try {
        conn.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值