Spring AMQP学习之RabbitAdmin

目录

 

官方地址 4.1.11. Configuring the Broker

RabbitAdmin是什么角色?

AmqpAdmin定义了哪些接口?

默认实现类RabbitAdmin

通过rabbitAdmin设置忽略声明异常以及监听异常信息

通过rabbitAdmin设置Headers Exchange

通过java配置AMQP 基础骨架

1.6提供了建造者模式创建队列和交换机

批量声明组件

有条件的声明(非启动声明)


官方地址 4.1.11. Configuring the Broker

RabbitAdmin是什么角色?

AMQP规范中指定了如何配置queues, exchanges, and bindings on the broker.这部分操作表现在org.springframework.amqp.core包下的AmqpAdmin接口(适配0.8及以上规范),RabbitMQ 实现类是org.springframework.amqp.rabbit.core包下的RabbitAdmin 。

总结一下就是:AmqpAdmin接口定义了如何配置queues,exchanges,and bindings on the broker.RabbitAdmin实现了这个接口,做了具体操作。RabbitAdmin的作用是声明队列,交换机在broker上的绑定关系

AmqpAdmin定义了哪些接口?

public interface AmqpAdmin {

    // Exchange Operations
    // 声明交换机
    void declareExchange(Exchange exchange);
    // 删除交换机
    void deleteExchange(String exchangeName);

    // Queue Operations
    /**
      *声明队列,队列名字自动生成
      * 队列属性 exclusive=true, autoDelete=true, and durable=false
      */
    Queue declareQueue();

    /**
      * 声明队列 返回队列名称
      * name属性为空的队列称为 AnonymousQueue,匿名队列会生成一个uuid名称,
      * durable=false,exclusive=true,autoDelete=true
      * 2.1以后,匿名内部类会将x-queue-master-locator设置为client-local
      */
    String declareQueue(Queue queue);
    //删除队列
    void deleteQueue(String queueName);
    //删除队列
    void deleteQueue(String queueName, boolean unused, boolean empty);
    //清空队列
    void purgeQueue(String queueName, boolean noWait);

    // Binding Operations
    //声明绑定
    void declareBinding(Binding binding);
    //移除绑定
    void removeBinding(Binding binding);
    /**获取队列属性
     *队列消息count 消费者count ...
     */
    Properties getQueueProperties(String queueName);

}

默认实现类RabbitAdmin

基于spring xml的配置:



CachingConnectionFactory设置为CHANNEL模式时,RabbitAdmin会自动在同一个上下文applicationContext中延迟(当第一个连接连通broker时)声明队列,交换机和绑定关系。

通过rabbitAdmin设置忽略声明异常以及监听异常信息

默认情况下,RabbitAdmin 会在有异常发生时直接停止所有的组件声明,这会导致一个队列的声明异常影响后续队列的声明。为了避免这种情况,可以将RabbitAdmin的属性ignore-declaration-exceptions设置为true,这个设置使得RabbitAdmin可以打印异常日志然后接着声明其他元素。在java中这个属性key为ignoreDeclarationExceptions,在异常发生时,会发布一个DeclarationExceptionEvent事件,这个事件是ApplicationEvent 类型的,可以通过容器中的ApplicationListener 来进行监听,事件源包含了admin的映射,声明的元素以及抛出的异常。

通过rabbitAdmin设置Headers Exchange


    
        
            
                
                
                
            
        
    

1.6以后,可以通过rabbitAdmin将交换机设置一个internal属性(默认为false),当这个属性设置为true时,RabbitMq不会让客户端使用这个交换机,这在设置死信交换机或者exchange-to-exchange binding的时候非常有用,这样可以不用担心别人往这个交换机上发布消息。

通过java配置AMQP 基础骨架

@Configuration
public abstract class AbstractStockAppRabbitConfiguration {

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory =
            new CachingConnectionFactory("localhost");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        return connectionFactory;
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setMessageConverter(jsonMessageConverter());
        configureRabbitTemplate(template);
        return template;
    }

    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public TopicExchange marketDataExchange() {
        return new TopicExchange("app.stock.marketdata");
    }

    // additional code omitted for brevity

}

基于AbstractStockAppRabbitConfiguration 配置的server端配置。项目启动时会自动声明TopicExchange 和Queue ,server端没有绑定TopicExchange和Queue,这部分由client端来完成,server端的这个队列会绑定到默认的交换机上。

@Configuration
public class RabbitServerConfiguration extends AbstractStockAppRabbitConfiguration  {

    @Bean
    public Queue stockRequestQueue() {
        return new Queue("app.stock.request");
    }
}

基于AbstractStockAppRabbitConfiguration 配置的client端配置

@Configuration
public class RabbitClientConfiguration extends AbstractStockAppRabbitConfiguration {

    @Value("${stocks.quote.pattern}")
    private String marketDataRoutingKey;

    /**
      * 通过AmqpAdmin的declareQueue声明一个队列
    @Bean
    public Queue marketDataQueue() {
        return amqpAdmin().declareQueue();
    }

    /**
     * 绑定market data exchange 监听任何匹配routing key的消息
     */
    @Bean
    public Binding marketDataBinding() {
        return BindingBuilder.bind(
                marketDataQueue()).to(marketDataExchange()).with(marketDataRoutingKey);
    }

    // additional code omitted for brevity

}

1.6提供了建造者模式创建队列和交换机

@Bean
public Queue queue() {
    return QueueBuilder.nonDurable("foo")
        .autoDelete()
        .exclusive()
        .withArgument("foo", "bar")
        .build();
}

@Bean
public Exchange exchange() {
  return ExchangeBuilder.directExchange("foo")
      .autoDelete()
      .internal()
      .withArgument("foo", "bar")
      .build();
}

2.2版本优化了建造者模式

@Bean
public Queue allArgs1() {
    return QueueBuilder.nonDurable("all.args.1")
            .ttl(1000)
            .expires(200_000)
            .maxLength(42)
            .maxLengthBytes(10_000)
            .overflow(Overflow.rejectPublish)
            .deadLetterExchange("dlx")
            .deadLetterRoutingKey("dlrk")
            .maxPriority(4)
            .lazy()
            .masterLocator(MasterLocator.minMasters)
            .singleActiveConsumer()
            .build();
}

@Bean
public DirectExchange ex() {
    return ExchangeBuilder.directExchange("ex.with.alternate")
            .durable(true)
            .alternate("alternate")
            .build();
}

批量声明组件

@Configuration
public static class Config {

    @Bean
    public ConnectionFactory cf() {
        return new CachingConnectionFactory("localhost");
    }

    @Bean
    public RabbitAdmin admin(ConnectionFactory cf) {
        return new RabbitAdmin(cf);
    }

    @Bean
    public DirectExchange e1() {
    	return new DirectExchange("e1", false, true);
    }

    @Bean
    public Queue q1() {
    	return new Queue("q1", false, false, true);
    }

    @Bean
    public Binding b1() {
    	return BindingBuilder.bind(q1()).to(e1()).with("k1");
    }

    @Bean
    public Declarables es() {
        return new Declarables(
                new DirectExchange("e2", false, true),
                new DirectExchange("e3", false, true));
    }

    @Bean
    public Declarables qs() {
        return new Declarables(
                new Queue("q2", false, false, true),
                new Queue("q3", false, false, true));
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Declarables prototypes() {
        return new Declarables(new Queue(this.prototypeQueueName, false, false, true));
    }

    @Bean
    public Declarables bs() {
        return new Declarables(
                new Binding("q2", DestinationType.QUEUE, "e2", "k2", null),
                new Binding("q3", DestinationType.QUEUE, "e3", "k3", null));
    }

    @Bean
    public Declarables ds() {
        return new Declarables(
                new DirectExchange("e4", false, true),
                new Queue("q4", false, false, true),
                new Binding("q4", DestinationType.QUEUE, "e4", "k4", null));
    }

}

2.2版本为Declarables添加了getDeclarablesByType 方法,在声明listener container时更加方便。

public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
        Declarables mixedDeclarables, MessageListener listener) {

    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
    container.setQueues(mixedDeclarables.getDeclarablesByType(Queue.class).toArray(new Queue[0]));
    container.setMessageListener(listener);
    return container;
}

有条件的声明(非启动声明)

默认的,所有的queues, exchanges, and bindings 都是被所有的RabbitAdmin 实例以auto-startup="true"的方式在容器中声明。2.1.9以后,RabbitAdmin 有一个新的属性explicitDeclarationsOnly (默认false),当这个属性设置为true时,rabbitadmin只会在声明哪些被明确指定要声明的beans。每个元素都实现了Declarable,Declarable有两个方法,一个是shouldDeclare() ,一个是getDeclaringAdmins(),rabbitadmin通过这两个方法来决定是否声明这个bean。

一个配置例子:



















	
		
	

2.0版本如果同时为一个元素设置了id和name,那么name不会被注册为别名,如果想要将queue和exchange注册为同一个名字,那么必须提供id。如果只有一个name,那么bean在binding时仍然可以通过name来影射,如果名字中由ApEL表达式,那么bean在binding时不可以通过name来影射。

 

 

 

 

 

 

 

你可能感兴趣的:(Spring,AMQP)