rabbitmq spring api

1 连接 (消费者和接受者都需要使用)

@Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses("127.0.0.1");
        connectionFactory.setHost("5672");
        connectionFactory.setUsername("jack");
        connectionFactory.setPassword("123456");
        connectionFactory.setVirtualHost("/");
        connectionFactory.setPublisherConfirms(true); // publisher确认模式
        connectionFactory.setPublisherReturns(true); // publisher没有路由返回
        connectionFactory.setConnectionTimeout(6 * 1000);  //ting.cai 1212 超时6s
        return connectionFactory;
    }


2 消费者


public class Receiver implements ChannelAwareMessageListener {

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        System.out.println(" 消费者接收到消息:" + new String(message.getBody(),"utf-8"));
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);// 手动确认消息收到ack
    }
}


@Bean
    Receiver receiver(){
        return new Receiver();
    }


    @Bean
    SimpleMessageListenerContainer myListenerContainer(ConnectionFactory connectionFactory,
                                             Receiver receiver) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames("myQueue");
        container.setMessageListener(receiver);

//  NONE 和自动差不多,只不过broker认为consumer是不会发送任何ack  

        //  MANUAL 手动  AUTO 自动确认,onMessage()方法抛出异常例外
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return container;
    }


3 生产者


3.1 channel的缓存

@Bean
RabbitTemplate myTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        return template;
}


实际上是一个channel的缓存,默认有25个channel,发送消息时,会从缓存中取空闲的channel,底层再通过channel发送

注意:设置的确认回调方法会被template里面所有缓存channel所共有,所以必须考虑所有使用这个template发送消息业务是否兼容这个回调

所以我建议对于使用confirm回调,本业务的发送和确认回调监听应该使用使用connectionfactory重新创建一个template


myTemplate.setConfirmCallback((CorrelationData correlationData, boolean ack, String errorMsg) -> {
      if(ack){
            System.out.println("ack==> confirm:correlationData=" + correlationData.getId() + " ack= " + ack);

            unAckMessageMap.remove(correlationData.getId());

      }

}


无法投递到queue的回调也有同样channel缓存问题

myTemplate.setMandatory(true);// 强制投递,投递不到queue才会回调

myTemplate.setReturnCallback((Message message, int replyCode, String replyText,
                                      String exchange, String routingKey)->{
            
 });


3.2 申明broker的queue、exchange、binding

@Bean
    public Queue myQueue(){
        return new  Queue("myQueue");
    }


    @Bean
    DirectExchange myExchange() {
        return new DirectExchange("myExchange");
    }


    @Bean
    Binding myBinding(Queue myQueue, DirectExchange myExchange) {
        return BindingBuilder.bind(myQueue).to(myExchange).with("myRoutingKey");
    }

    // AmqpAdmin会激活queue,binding,exchange,否则未激活状态
    @Bean
    public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory,
                                Queue myQueue,
                               DirectExchange myExchange,
                               Binding myBinding) {
        RabbitAdmin rabbitAdmin =  new RabbitAdmin(connectionFactory);


        // 如果队列不存在,可以自动创建一个
        rabbitAdmin.declareQueue(myQueue);
        rabbitAdmin.declareExchange(myExchange);
        rabbitAdmin.declareBinding(myBinding);
        return rabbitAdmin;
    }

3.3 发送

String id = getId();
// 指定投递的exchage和路由键
myTemplate.convertAndSend("myExchange","myRoutingKey","hello the world {id = " +  id + "}", new CorrelationData(id));
unAckMessageMap.put(id,"hello the world");



   



猜你喜欢

转载自blog.csdn.net/ShuaiFanPi/article/details/80153511
今日推荐