SpringBoot中配置RabbitMQ

一. yaml配置文件

spring:
  rabbitmq:
    host: 192.168.70.167
    port: 5672
    username: admin
    password: public
    #    virtual-host: GHost
    virtual-host: /

    # 确认消息已发送到交换机
    publisher-confirms: true
    # 消息发送失败后返回
    publisher-returns: true

    listener:
      # 默认配置是simple
      type: simple
      simple:
        # 手动ack Acknowledge mode of container. auto none
        acknowledge-mode: manual
        # Maximum number of unacknowledged messages that can be outstanding at each consumer.
        prefetch: 3

二. 配置RabbitTemplate

@Configuration
public class RabbitTemplateConfig {

    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate=new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);

        rabbitTemplate.setMandatory(true);

        //推送到server回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) ->
                log.info("ConfirmCallback correlationData:{},ack:{},cause:{}",correlationData,ack,cause));

        //消息返回给生产者, 路由不到队列时返回给发送者  先returnCallback,再 confirmCallback
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            log.info("ReturnCallback message:{},replyCode:{},replyText:{},exchange:{},routingKey:{}",
                    message,replyCode,replyText,exchange,routingKey);
        });
        return rabbitTemplate;
    }
}

三. 消息发送

将rabbitTemplate注入相应的类中即可发送消息

@RestController
@RequestMapping("mqTest1")
public class MqTest1Controller {

    @Autowired
    RabbitTemplate rabbitTemplate;
    
    @GetMapping("streamPush")
    public String streamPush(){
        rabbitTemplate.convertAndSend(HeadersRabbitConfig.HEADERS_EXCHANGE_NAME,"","I am a msg".getBytes(),message -> {
            Map<String,Object> headers=message.getMessageProperties().getHeaders();
            headers.put("format","pdf");
            //headers.put("type","report");
            headers.put("han","shaohua");
            return message;
        });
        return "hehe";
    }
}

四. 配置接收消息的Listener

listener负责监听队列

@Component
@RabbitListener(queues = {TopicRabbitConfig.TOPIC_QUEUE_NAME})
public class TopicHandler2 {

    @RabbitHandler
    public void processByteMsg(@Headers MessageHeaders headers, byte[] msgPayload) {
        String msg = new String(msgPayload);
        log.info("TopicHandler2收到消息:{},exchange:{},routingKey:{},queue:{}",
                msg, headers.get("amqp_receivedExchange"),
                headers.get("amqp_receivedRoutingKey"),
                headers.get("amqp_consumerQueue"));
    }

    @RabbitHandler
    public void processStringMsg(@Headers MessageHeaders headers, Channel channel, String msg,
                                 @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag,
                                 @Header(AmqpHeaders.CONSUMER_TAG) String consumerTag) throws Exception {
        log.info("TopicHandler2收到消息:{},exchange:{},routingKey:{},queue:{}",
                msg, headers.get("amqp_receivedExchange"),
                headers.get("amqp_receivedRoutingKey"),
                headers.get("amqp_consumerQueue"));
        channel.basicAck(deliveryTag, false);
        //拒绝消息, requeue为true会重入队列, 消息就会一直接受
        //channel.basicNack(deliveryTag,false,false);
        //channel.basicCancel(consumerTag);
    }

}

五. 不同类型的exchange配置队列与绑定关系

1. Fanout

Fanout类型的exchange会忽略routingKey,所以配置中无法设置routingKey

@Configuration
public class FanoutRabbitConfig {

    public static final String FANOUT_QUEUE_NAME="htFanoutQueue";
    public static final String FANOUT_EXCHANGE_NAME="htFanoutExchange";
    
    //发送消息时只需要创建exchange即可
    @Bean
    FanoutExchange fanoutExchange(){
        return new FanoutExchange(FANOUT_EXCHANGE_NAME);
    }

    @Bean
    public Queue fanoutQueue(){
        //durable:true mq服务器重启后仍然存在 false重启后队列自动删除
        return new Queue(FANOUT_QUEUE_NAME,false);
    }

    /**
     * 队列绑定fanout类型的exchange是无法设置routingKey
     * @return
     */
    @Bean
    Binding bindingFanout(){
        return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());
    }
}

2. Direct

/**
 * direct类型exchange routingKey匹配
 */
@Configuration
public class DirectRabbitConfig {

    static final String DIRECT_QUEUE_NAME="htDirectQueue";
    public static final String DIRECT_EXCHANGE_NAME="htDirectExchange";
    public static final String ROUTING_KEY="htDirectRouting";

    //发送消息是只需要创建exchange即可
    @Bean
    DirectExchange directExchange(){
        return new DirectExchange(DIRECT_EXCHANGE_NAME);
    }

    //接收消息是需要声明队列,然后通过routingKey将队列与exchange绑定
    @Bean
    public Queue directQueue(){
        return new Queue(DIRECT_QUEUE_NAME,false);
    }

    @Bean
    Binding bindingDirect(){
        return BindingBuilder.bind(directQueue()).to(directExchange()).with(ROUTING_KEY);
    }
}

3. Topic

@Configuration
public class TopicRabbitConfig {

    static final String TOPIC_QUEUE_NAME="htTopicQueue";
    static final String TOPIC_QUEUE1_NAME="htTopicQueue1";

    public static final String TOPIC_EXCHANGE_NAME="htTopicExchange";
    /**
     * #匹配0个或多个单词,*匹配一个单词,即使一个的多个routingKey都匹配上了,但该队列只收到一次消息
     */
    public static final String TOPIC="htTopicRouting.*";
    public static final String TOPIC1="htTopicRouting.topic1";


    //发送消息是只需要创建exchange即可
    @Bean
    TopicExchange topicExchange(){
        return new TopicExchange(TOPIC_EXCHANGE_NAME);
    }

    //接收消息是需要声明队列,然后通过routingKey将队列与exchange绑定

    //带通配符的topic
    @Bean
    public Queue topicQueue(){
        //durable:true mq服务器重启后让然存在 false重启后队列自动删除
        return new Queue(TOPIC_QUEUE_NAME,false);
    }
    @Bean
    Binding bindingTopic(){
        return BindingBuilder.bind(topicQueue()).to(topicExchange()).with(TOPIC);
    }

    //topic1
    @Bean
    public Queue topicQueue1(){
        return new Queue(TOPIC_QUEUE1_NAME,false);
    }
    @Bean
    Binding bindingTopic1(){
        return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with(TOPIC1);
    }
}

4. Headers

@Configuration
public class HeadersRabbitConfig {

    static final String HEADERS_QUEUE_NAME="htHeadersQueue";
    public static final String HEADERS_EXCHANGE_NAME="htHeadersExchange";

    //发送消息是只需要创建exchange即可
    @Bean
    HeadersExchange headersExchange(){
        return new HeadersExchange(HEADERS_EXCHANGE_NAME);
    }

    @Bean
    public Queue headersQueue(){
        return new Queue(HEADERS_QUEUE_NAME,false);
    }

    @Bean
    Binding bindingDirect(){
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("format",  "pdf");
        arguments.put("type",  "report");
        //x-match为any
        return BindingBuilder.bind(headersQueue()).to(headersExchange()).whereAny(arguments).match();
    }

    @Bean
    Binding bindingAllDirect(){
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("format",  "pdf");
        arguments.put("type",  "report");
        //x-match为all
        return BindingBuilder.bind(headersQueue()).to(headersExchange()).whereAll(arguments).match();
    }
}

你可能感兴趣的:(RabbitMQ指南,rabbitmq,spring,boot,java)