spring boot2.1集成RabbitMQ

转载请表明出处 https://blog.csdn.net/Amor_Leo/article/details/85085697 谢谢

简单介绍

RabbitMQ 即消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发,削峰等作用.RabbitMQ使用的是AMQP(高级消息队列协议).默认启动端口 5672,UI界面15672.

Direct是RabbitMQ默认的交换机模式,也是最简单的模式,直连模式.即创建消息队列的时候,指定一个RouteKey.当发送者发送消息的时候,指定对应的Key.当Key和消息队列的RouteKey一致的时候,消息将会被发送到该消息队列中.也可以使用rabbitMQ自带的Exchange:default Exchange 。所以不需要将Exchange进行任何绑定(binding)操作 。消息传递时,RouteKey必须完全匹配,才会被队列接收,否则该消息会被抛弃。

topic转发信息主要是依据通配符,队列和交换机的绑定主要是依据一种模式(通配符+字符串),而当发送消息的时候,只有指定的Key和该模式相匹配的时候,消息才会被发送到该消息队列中.其中* 一个字,# 0个或多个字.

Fanout是路由广播的模式,将会把消息发给绑定它的全部队列,即便设置了key,也会被忽略.

headers也是根据一个规则进行匹配,在消息队列和交换机绑定的时候会指定一组键值对规则,而发送消息的时候也会指定一组键值对规则,当两组键值对规则相匹配的时候,消息会被发送到匹配的消息队列中.

安装RabbitMQ

Erlang语言写的,安装Rabbit,必须Erlang语言的运行环境。

Docker能打包安装环境,使用docker,很容易解决这个问题。

放行虚拟机端口

firewall-cmd --zone=public --add-port=端口号/tcp --permanent  
firewall-cmd --reload

获取镜像:

docker pull rabbitmq:management

运行实例:

docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq:management

添加依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
   </dependencies>

简单配置

简单yml配置

spring:
  rabbitmq:
    host: 192.168.0.114
    port: 5672
    username: admin
    password: admin
    virtual-host: /

配置类

/**
 * @author: LHL
 * @ProjectName: rabbitmq
 * @Package: com.amor.config
 * @ClassName: RabbitmqConf
 * @Date: 2018/11/18 21:06
 * @Description:
 * @Version: 1.0
 */
@Configuration
public class RabbitmqConf {
    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitmqConf.class);

    /**
     * 消息交换机的名字
     * */
    private static final String DIRECT_EXCHANGE = "DirectExchange";

    private static final String TOPIC_EXCHANGE = "TopicExchange";

    private static final String FANOUT_EXCHANGE ="FanoutExchange" ;

    private static final String HEADERS_EXCHANGE ="HeadersExchange" ;

    /**
     * 队列的名字
     * */
    private static final String DIRECT_QUEUE = "DirectQueue";

    private static final String TOPIC_QUEUE = "TopicQueue";

    private static final String FANOUT_QUEUE = "FanoutQueue";

    private static final String HEADERS_QUEUE = "HeadersQueue";

    /**
     * key
     * */
    private static final String DIRECT_KEY = "DirectKey";

    private static final String TOPIC_KEY = "Topic.#";

    /**
     * 1.队列名字
     * 2.durable="true" 是否持久化 rabbitmq重启的时候不需要创建新的队列
     * 3.auto-delete    表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive      表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean
    public Queue dirctQueue() {
        return new Queue(DIRECT_QUEUE,true,false,false);
    }

    @Bean
    public Queue topicQueue() {
        return new Queue(TOPIC_QUEUE,true,false,false);
    }


    @Bean
    public Queue fanoutQueue() {
        return new Queue(FANOUT_QUEUE,true,false,false);
    }

    @Bean
    public Queue headersQueue() {
        return new Queue(HEADERS_QUEUE,true,false,false);
    }
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange(DIRECT_EXCHANGE,true,false);
    }

    /**
     * 1.交换机名字
     * 2.durable="true" 是否持久化 rabbitmq重启的时候不需要创建新的交换机
     * 3.autoDelete    当所有消费客户端连接断开后,是否自动删除队列
     */
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(TOPIC_EXCHANGE,true,false);
    }

    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(FANOUT_EXCHANGE,true,false);
    }

    @Bean
    public HeadersExchange headersExchange() {
        return new HeadersExchange(HEADERS_EXCHANGE,true,false);
    }

    /**
     * 将direct队列和交换机进行绑定
     */
    @Bean
    public Binding bindingDirect() {
        return BindingBuilder.bind(dirctQueue()).to(directExchange()).with(DIRECT_KEY);
    }

    @Bean
    public Binding bindingTopic() {
        return BindingBuilder.bind(topicQueue()).to(topicExchange()).with(TOPIC_KEY);
    }


    @Bean
    public Binding bindingFanout() {
        return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding headersBinding(){
        Map<String,Object> map = new HashMap<>();
        map.put("headers1","value1");
        map.put("headers2","value2");
        return BindingBuilder.bind(headersQueue()).to(headersExchange()).whereAll(map).match();
    }

    /**
     * 定义消息转换实例  转化成 JSON 传输  传输实体就可以不用实现序列化
     * */
    @Bean
    public MessageConverter integrationEventMessageConverter() {
        return  new Jackson2JsonMessageConverter();
    }
}

测试controller

/**
 * @author: LHL
 * @ProjectName: rabbitmq
 * @Package: com.amor.controller
 * @ClassName: RabbitmqController
 * @Date: 2018/11/18 21:33
 * @Description:
 * @Version: 1.0
 */
@RestController
public class RabbitmqController {
    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitmqController.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * @Description: 发送消息
     * 1.交换机
     * 2.key
     * 3.消息
     * 4.消息ID
     * rabbitTemplate.send(message);   发消息;参数对象为org.springframework.amqp.core.Message
     * rabbitTemplate.convertAndSend(message); 转换并发送消息;将参数对象转换为org.springframework.amqp.core.Message后发送,消费者不能有返回值
     * rabbitTemplate.convertSendAndReceive(message) //转换并发送消息,且等待消息者返回响应消息.消费者可以有返回值
     * @method: handleMessage
     * @Param: message
     * @return: void
     * @auther: LHL
     * @Date: 2018/11/18 21:40
     */
    @GetMapping("/directSend")
    public void directSend() {
        String message="direct 发送消息";
        rabbitTemplate.convertAndSend("DirectExchange","DirectKey",
                message, new CorrelationData(UUID.randomUUID().toString()));
    }

    @GetMapping("/topicSend")
    public void topicSend() {
        String message="topic 发送消息";
        rabbitTemplate.convertAndSend("TopicExchange","Topic.Key",
                message, new CorrelationData(UUID.randomUUID().toString()));
    }

    @GetMapping("/fanoutSend")
    public void fanoutSend() {
        String message="fanout 发送消息";
        rabbitTemplate.convertAndSend("FanoutExchange","",message, new CorrelationData(UUID.randomUUID().toString()));
    }

    @GetMapping("/headersSend")
    public void headersSend(){
        String msg="headers 发送消息";
        MessageProperties properties = new MessageProperties();
        properties.setHeader("headers1","value1");
        properties.setHeader("headers2","value2");
        Message message = new Message(msg.getBytes(),properties);
        rabbitTemplate.convertAndSend("HeadersExchange","",message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * @Description: 消费消息
     * @method: handleMessage
     * @Param: message
     * @return: void
     * @auther: LHL
     * @Date: 2018/11/18 21:41
     */
    @RabbitListener(queues = "DirectQueue")
    @RabbitHandler
    public void directMessage(String message){
        LOGGER.info("DirectConsumer {} directMessage :"+message);
    }

    @RabbitListener(queues = "TopicQueue")
    @RabbitHandler
    public void topicMessage(String message){
        LOGGER.info("TopicConsumer {} topicMessage :"+message);
    }

    @RabbitListener(queues = "FanoutQueue")
    @RabbitHandler
    public void fanoutMessage(String message){
        LOGGER.info("FanoutConsumer {} fanoutMessage :"+message);
    }

    @RabbitListener(queues = "HeadersQueue")
    @RabbitHandler
    public void headersMessage(Message message){ 
    	LOGGER.info("HeadersConsumer {} headersMessage :"+message);
    }
}

开启消息发送交换机确认和队列与交换器是否绑定确认

yml配置

spring:
  rabbitmq:
    host: 192.168.0.114
    port: 5672
    username: admin
    password: admin
    virtual-host: /
    # 开启发送确认
    publisher-confirms: true
    # 开启发送失败退回
    publisher-returns: true
    listener:
      direct:
        retry:
          enabled: true #消费者端的重试
      simple:
        retry:
          enabled: true #消费者端的重试
    template:
      reply-timeout: 10000 #超时时间
      retry:
        enabled: true  #设置为true的时候RabbitTemplate(生产端)能够实现重试

配置类

/**
 * @author: LHL
 * @ProjectName: rabbitmq
 * @Package: com.amor.config
 * @ClassName: RabbitSender
 * @Date: 2018/11/18 23:24
 * @Description:
 * @Version: 1.0
 */
@Service
public class RabbitSender implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {

    private final Logger logger = LoggerFactory.getLogger(RabbitSender.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
    }

    /**
     * 实现消息发送到RabbitMQ交换器后接收ack回调,如果消息发送确认失败就进行重试.
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            logger.info("消息发送成功,消息ID:{}", correlationData.getId());
        } else {
            logger.info("消息发送失败,消息ID:{}", correlationData.getId());
        }
    }

    /**
     * 实现消息发送到RabbitMQ交换器,但无相应队列与交换器绑定时的回调.
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        logger.error("消息发送失败,replyCode:{}, replyText:{},exchange:{},routingKey:{},消息体:{}",replyCode, replyText, exchange, routingKey, new String(message.getBody()));
    }

   /**
     * convertAndSend 异步,消息是否发送成功用ConfirmCallback和ReturnCallback回调函数类确认。
     * 发送MQ消息
     */
    public void sendMessage(String exchangeName, String routingKey, Object message) {
        rabbitTemplate.convertAndSend(exchangeName, routingKey, message, new CorrelationData(UUID.randomUUID().toString()));
    }

    /**
     * sendMessageAndReturn 当发送消息过后,该方法会一直阻塞在哪里等待返回结果,直到请求超时,配置spring.rabbitmq.template.reply-timeout来配置超时时间。
     * 发送MQ消息并返回结果
     */
    public Object sendMessageAndReturn(String exchangeName, String routingKey, Object message) {
        return rabbitTemplate.convertSendAndReceive(exchangeName, routingKey, message, new CorrelationData(UUID.randomUUID().toString()));
    }
}
/**
 * @author: LHL
 * @ProjectName: rabbitmq
 * @Package: com.amor.controller
 * @ClassName: RabbitmqController
 * @Date: 2018/11/18 21:33
 * @Description:
 * @Version: 1.0
 */
@RestController
public class RabbitmqController {
    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitmqController.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitSender rabbitSender;

    /**
     * @Description: 发送消息
     * 1.交换机
     * 2.key
     * 3.消息
     * 4消息ID
     * rabbitTemplate.send(message);   发消息;参数对象为org.springframework.amqp.core.Message
     * rabbitTemplate.convertAndSend(message); 转换并发送消息;将参数对象转换为org.springframework.amqp.core.Message后发送,消费者不能有返回值
     * rabbitTemplate.convertSendAndReceive(message) //转换并发送消息,且等待消息者返回响应消息.消费者可以有返回值
     * @method: handleMessage
     * @Param: message
     * @return: void
     * @auther: LHL
     * @Date: 2018/11/18 21:40
     */
    @GetMapping("/directSend")
    public void directSend() {
        String message = "direct 发送消息";
        //rabbitTemplate.convertAndSend("DirectExchange", "DirectKey", message, new CorrelationData(UUID.randomUUID().toString()));
        rabbitSender.sendMessage("DirectExchange", "DirectKey", message);

    }

    @GetMapping("/topicSend")
    public void topicSend() {
        String message = "topic 发送消息";
        //rabbitTemplate.convertAndSend("TopicExchange", "Topic.Key", message, new CorrelationData(UUID.randomUUID().toString()));
        rabbitSender.sendMessage("TopicExchange", "Topic.Key", message);
    }

    @GetMapping("/fanoutSend")
    public void fanoutSend() {
        String message = "fanout 发送消息";
        //rabbitTemplate.convertAndSend("FanoutExchange", "", message, new CorrelationData(UUID.randomUUID().toString()));
        rabbitSender.sendMessage("FanoutExchange", "", message);
    }

    @GetMapping("/headersSend")
    public void headersSend() {
        String msg = "headers 发送消息";
        MessageProperties properties = new MessageProperties();
        properties.setHeader("headers1", "value1");
        properties.setHeader("headers2", "value2");
        Message message = new Message(msg.getBytes(), properties);
        //rabbitTemplate.convertAndSend("HeadersExchange","",message, new CorrelationData(UUID.randomUUID().toString()));
        rabbitSender.sendMessage("HeadersExchange", "", message);
    }

    /**
     * @Description: 消费消息
     * @method: handleMessage
     * @Param: message
     * @return: void
     * @auther: LHL
     * @Date: 2018/11/18 21:41
     */
    @RabbitListener(queues = "DirectQueue")
    @RabbitHandler
    public void directMessage(String sendMessage) {
           LOGGER.info("DirectConsumer {} directMessage :" + message);
    }

    @RabbitListener(queues = "TopicQueue")
    @RabbitHandler
    public void topicMessage(String message) {
        LOGGER.info("TopicConsumer {} topicMessage :" + message);
    }

    @RabbitListener(queues = "FanoutQueue")
    @RabbitHandler
    public void fanoutMessage(String message) {
        LOGGER.info("FanoutConsumer {} fanoutMessage :" + message);
    }

    @RabbitListener(queues = "HeadersQueue")
    @RabbitHandler
    public void headersMessage(Message message) {
        LOGGER.info("HeadersConsumer {} headersMessage :" + message);
    }
}

开启ACK手动确认模式

手动确认配置

第一种直接yml配置

spring:
  rabbitmq:
    host: 192.168.0.114
    port: 5672
    username: admin
    password: admin
    virtual-host: /
    # 开启发送确认
    publisher-confirms: true
    # 开启发送失败退回
    publisher-returns: true
    listener:
      direct:
        acknowledge-mode: manual      # 开启ACK
        retry:
          enabled: true #消费者端的重试
      simple:
        retry:
          enabled: true #消费者端的重试
        acknowledge-mode: manual         # 开启ACK
        concurrency: 10  #消费者的最小数量
        max-concurrency: 20  #消费者的最大数量
        prefetch: 5  #在单个请求中处理的消息个数,他应该大于等于事务数量
        auto-startup: true  #启动时自动启动容器	true
        default-requeue-rejected: true  #投递失败时是否重新排队
    template:
      reply-timeout: 10000 #超时时间
      retry:
        enabled: true  #设置为true的时候RabbitTemplate(生产端)能够实现重试
        initial-interval: 1000  #第一次与第二次发布消息的时间间隔 1000
        max-attempts: 3 #尝试发布消息的最大数量 3
        max-interval: 10000  #尝试发布消息的最大时间间隔 10000
        multiplier: 1.0  #上一次尝试时间间隔的乘数 1.0
 /**
     * @Description: 消费消息
     * @method: handleMessage
     * @Param: message
     * @return: void
     * @auther: LHL
     * @Date: 2018/11/18 21:41
     */
    @RabbitListener(queues = "DirectQueue")
    @RabbitHandler
    public void directMessage(String sendMessage, Channel channel, Message message) throws Exception {
        try {
            Assert.notNull(sendMessage, "sendMessage 消息体不能为NULL");
            LOGGER.info("处理MQ消息");
            // prefetchCount限制每个消费者在收到下一个确认回执前一次可以最大接受多少条消息,通过basic.qos方法设置prefetch_count=1,这样RabbitMQ就会使得每个Consumer在同一个时间点最多处理一个Message
                channel.basicQos(1);
            LOGGER.info("DirectConsumer {} directMessage :" + message);
            // 确认消息已经消费成功
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            LOGGER.error("MQ消息处理异常,消息ID:{},消息体:{}", message.getMessageProperties().getCorrelationId(),sendMessage,e);
            // 拒绝当前消息,并把消息返回原队列
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }

第二种配置类配置

spring:
  rabbitmq:
    host: 192.168.0.114
    port: 5672
    username: admin
    password: admin
    virtual-host: /
    # 开启发送确认
    publisher-confirms: true
    # 开启发送失败退回
    publisher-returns: true
    listener:
      direct:
        retry:
          enabled: true #消费者端的重试
      simple:
        retry:
          enabled: true #消费者端的重试
        auto-startup: true  #启动时自动启动容器	true
        default-requeue-rejected: true  #投递失败时是否重新排队
    template:
      reply-timeout: 10000 #超时时间
      retry:
        enabled: true  #设置为true的时候RabbitTemplate(生产端)能够实现重试
        initial-interval: 1000  #第一次与第二次发布消息的时间间隔 1000
        max-attempts: 3 #尝试发布消息的最大数量 3
        max-interval: 10000  #尝试发布消息的最大时间间隔 10000
        multiplier: 1.0  #上一次尝试时间间隔的乘数 1.0
/**
 * @author: LHL
 * @ProjectName: rabbitmq
 * @Package: com.amor.config
 * @ClassName: RabbitmqConf
 * @Date: 2018/11/18 21:06
 * @Description:
 * @Version: 1.0
 */
@Configuration
public class RabbitmqConf {
    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitmqConf.class);

    @Value("${spring.rabbitmq.host}")
    private String addresses;

    @Value("${spring.rabbitmq.port}")
    private int port;

    @Value("${spring.rabbitmq.username}")
    private String username;

    @Value("${spring.rabbitmq.password}")
    private String password;

    @Value("${spring.rabbitmq.virtual-host}")
    private String virtualHost;

    @Value("${spring.rabbitmq.publisher-confirms}")
    private boolean publisherConfirms;

   @Value("${spring.rabbitmq.publisher-returns}")
    private boolean publisherReturns;

    /**
     * 消息交换机的名字
     * */
    private static final String DIRECT_EXCHANGE = "DirectExchange";

    private static final String TOPIC_EXCHANGE = "TopicExchange";

    private static final String FANOUT_EXCHANGE ="FanoutExchange" ;

    private static final String HEADERS_EXCHANGE ="HeadersExchange" ;

    /**
     * 队列的名字
     * */
    private static final String DIRECT_QUEUE = "DirectQueue";

    private static final String TOPIC_QUEUE = "TopicQueue";

    private static final String FANOUT_QUEUE = "FanoutQueue";

    private static final String HEADERS_QUEUE = "HeadersQueue";

    /**
     * key
     * */
    private static final String DIRECT_KEY = "DirectKey";

    private static final String TOPIC_KEY = "Topic.#";



    /**
     * @Description: 连接工厂
     * @method: connectionFactory
     * @Param:
     * @return: org.springframework.amqp.rabbit.connection.ConnectionFactory
     * @auther: LHL
     * @Date: 2018/11/18 23:41
     */
    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(addresses,port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        /** 如果要进行消息发送确认回调,则这里必须要设置为true */
        connectionFactory.setPublisherConfirms(publisherConfirms);
        /** 如果要进行消息发送失败退回,则这里必须要设置为true */
        connectionFactory.setPublisherReturns(publisherReturns);
        return connectionFactory;
    }

    /**
     * 因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置
     * */
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        return template;
    }

    @Bean
    public SimpleMessageListenerContainer messageContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
        /*container.setQueues(dirctQueue());*/
        container.setQueues(dirctQueue(),topicQueue(),fanoutQueue(),headersQueue());
        //将channel暴露给listener才能手动确认,AcknowledgeMode.MANUAL时必须为ture
        container.setExposeListenerChannel(true);
        //消费者的最大数量,并发消费的时候需要设置,且>=concurrentConsumers
        container.setMaxConcurrentConsumers(10);
        //消费者的最小数量
        container.setConcurrentConsumers(10);
        //在单个请求中处理的消息个数,他应该大于等于事务数量
        container.setPrefetchCount(1);
        //开启ACK  手动确认机制
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {
            try {
                // prefetchCount限制每个消费者在收到下一个确认回执前一次可以最大接受多少条消息,通过basic.qos方法设置prefetch_count=1,这样RabbitMQ就会使得每个Consumer在同一个时间点最多处理一个Message
                channel.basicQos(1);
                LOGGER.info("ACK消费端接收到消息:" + message.getMessageProperties() + ":" + new String(message.getBody()));
                LOGGER.info("当前使用路由key:"+message.getMessageProperties().getReceivedRoutingKey());
                // deliveryTag:消息传送的次数,发布的每一条消息都会获得一个唯一的deliveryTag,(任何channel上发布的第一条消息的deliveryTag为1,此后的每一条消息都会加1),deliveryTag在channel范围内是唯一的
                // multiple:批量确认标志。如果值为true,则执行批量确认,此deliveryTag之前收到的消息全部进行确认; 如果值为false,则只对当前收到的消息进行确认
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } catch (Exception e) {
                e.printStackTrace();
                if (message.getMessageProperties().getRedelivered()) {
                    LOGGER.info("消息已重复处理失败,拒绝再次接收...");
                    // deliveryTag:消息传送的次数,发布的每一条消息都会获得一个唯一的deliveryTag,deliveryTag在channel范围内是唯一的
                    // multiple:批量确认标志。如果值为true,包含本条消息在内的、所有比该消息deliveryTag值小的 消息都被拒绝了(除了已经被 ack 的以外);如果值为false,只拒绝三本条消息
                    // requeue:如果值为true,则重新放入RabbitMQ的发送队列,如果值为false,则通知RabbitMQ销毁这条消息
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
                } else {
                    LOGGER.info("消息即将再次返回队列处理...");
                    // deliveryTag:消息传送的次数,发布的每一条消息都会获得一个唯一的deliveryTag,deliveryTag在channel范围内是唯一的
                    // requeue:如果值为true,则重新放入RabbitMQ的发送队列,如果值为false,则通知RabbitMQ销毁这条消息
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                }
            }
        });
        return container;
    }


    /**
     * 1.队列名字
     * 2.durable="true" 是否持久化 rabbitmq重启的时候不需要创建新的队列
     * 3.auto-delete    表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive      表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean
    public Queue dirctQueue() {
        return new Queue(DIRECT_QUEUE,true,false,false);
    }

    @Bean
    public Queue topicQueue() {
        return new Queue(TOPIC_QUEUE,true,false,false);
    }


    @Bean
    public Queue fanoutQueue() {
        return new Queue(FANOUT_QUEUE,true,false,false);
    }

    @Bean
    public Queue headersQueue() {
        return new Queue(HEADERS_QUEUE,true,false,false);
    }
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange(DIRECT_EXCHANGE,true,false);
    }

    /**
     * 1.交换机名字
     * 2.durable="true" 是否持久化 rabbitmq重启的时候不需要创建新的交换机
     * 3.autoDelete    当所有消费客户端连接断开后,是否自动删除队列
     */
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(TOPIC_EXCHANGE,true,false);
    }

    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(FANOUT_EXCHANGE,true,false);
    }

    @Bean
    public HeadersExchange headersExchange() {
        return new HeadersExchange(HEADERS_EXCHANGE,true,false);
    }

    /**
     * 将direct队列和交换机进行绑定
     */
    @Bean
    public Binding bindingDirect() {
        return BindingBuilder.bind(dirctQueue()).to(directExchange()).with(DIRECT_KEY);
    }

    @Bean
    public Binding bindingTopic() {
        return BindingBuilder.bind(topicQueue()).to(topicExchange()).with(TOPIC_KEY);
    }


    @Bean
    public Binding bindingFanout() {
        return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding headersBinding(){
        Map<String,Object> map = new HashMap<>();
        map.put("headers1","value1");
        map.put("headers2","value2");
        return BindingBuilder.bind(headersQueue()).to(headersExchange()).whereAll(map).match();
    }

    /**
     * 定义消息转换实例  转化成 JSON 传输  传输实体就可以不用实现序列化
     * */
    @Bean
    public MessageConverter integrationEventMessageConverter() {
        return  new Jackson2JsonMessageConverter();
    }
}

猜你喜欢

转载自blog.csdn.net/Amor_Leo/article/details/85085697