参考:https://blog.csdn.net/a13627210064/article/details/82348059

 

参考:https://blog.csdn.net/u010288264/article/details/55260237     (1 2 3 4)

依賴:

<repositories><!-- 代码库 -->
        <repository>
            <id>maven-ali</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public//</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
                <checksumPolicy>fail</checksumPolicy>
            </snapshots>
        </repository>
    </repositories>

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

    <!--     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency> -->
        
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>




    </dependencies>
View Code

yml 配置连接

 

spring:
  rabbitmq:
#    host: 192.168.18.129
    addresses: 192.168.18.129:5672
    username: guest
    password: guest
#    支持发布确认
    publisher-confirms: true
#    支持发布返回
    publisher-returns: true
    listener:
      simple:
#        监听的最小线程数
        concurrency: 4
#        监听的最大线程数
        max-concurrency: 8
        retry:
          enabled: true
#         ack应答改模式:auto-自动,manual-手动,none-无应答
        acknowledge-mode: auto

 

 

生产者:发送消息

方式一:derict

配置:

package com.icil.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


//@Configuration
public class RabbitConfig {
    /********************************direct****************************************/
    // 交换机定义,这里我使用的是direct类型。大家可以根据自己的业务需求来指定对应的。下面会讲几种交换机的类型
                        // 对应的3个参数1.交换机名称 2.持久性保持标识 3.是否自动删除标识 
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange("name", false, false);
    }

    
    //创建一个队列
    @Bean(name = "queue")
    public Queue queue() {
        return QueueBuilder.durable("name").build();
    }
    
    
    //绑定队列到交换机上--with对应的是direct指定的具体key。
    @Bean
    public Binding binding(@Qualifier("queue") Queue queue,@Qualifier("directExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("key"); }
    

    
//    
//    /********************************topic****************************************/
//    
//    
//    @Bean
//    public TopicExchange topicExchange() {
//        /**
//         * TopicExchangeName
//         * 是否持久化
//         * 是否自动删除
//         */
//        return new TopicExchange("topicExchange", true, false);
//    }
//    
//    /**
//     * 创建一个队列,指定一个Exchange
//     * @return
//     */
//    @Bean(name = "topicQueue")
//    public Queue topicQueue() {
//        return QueueBuilder.durable("topicExchange").build();
//    }
//    
//    
//    @Bean
//    public Binding bindingtopic(@Qualifier("topicQueue") Queue queue, DirectExchange exchange) {
//        return BindingBuilder.bind(queue).to(exchange).with("A.B.C"); }
    
    
}
View Code

发送消息:

package com.icil.rabbitmq;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class RabbitProducer implements ConfirmCallback , ReturnCallback{

    private  static Logger  log =LoggerFactory.getLogger(RabbitProducer.class);
    
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    
    
    
    
     /** * 初始化确认发送回调及发送返回回调 */ 
    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
        }
    
    
      /**
     * 实现消息发送到RabbitMQ交换器后接收ack回调
     * @param correlationData
     * @param ack
     * @param cause
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        
         if (ack){ 
              // 发送成功 
             log.info("trainLink message send success ---"+System.currentTimeMillis() ); 
              } else { // 发送失败
                 log.error("trainLink message send failed because ---" + cause); 
             }
    }
    
    
    
    
/**
 *  * 实现消息发送到RabbitMQ交换器,但无相应队列与交换器绑定时的回调 
 *  * @param message
 *  * @param replyCode 
 *  * @param replyText 
 *  * @param exchange 
 *  * @param routingKey
 */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
//          log.error(message.getMessageProperties().getCorrelationIdString() + " send failed:error code " + replyCode + "mains:" + replyText);
         log.error(message.getMessageProperties().getClusterId() + " send failed:error code " + replyCode + "mains:" + replyText);
         
    }

    
     /** 
      * * 发送消息,供外部调用 
      * * ****** 重要 ******说明:发送时的方法选择 
      * * ****** 重要 ******convertAndSend属于不要求返回确认的 
      * * ****** 重要 ******convertSendAndReceive要求返回确认 
      * * ****** 重要 ******大家根据不同的业务场景进行选择, 
      * * 不返回确认可以理解为全异步; 
      * * 返回确认可以理解为异步处理,同步返回,存在一个生产者等待消费者的问题 
      * * 选择的原则一般为一致性要求较强的,要确认返回; 
      * * 一致性不强的,使用不返回确认,加大处理效率,免去等待时间 */
    
     public void sendSMSMessage(String msg){
         // fanout类型的交换器不需要routingkey,我这里用的是direct所以指定了对应的routingkey 
         this.rabbitTemplate.convertAndSend("name", "key", msg); 
//         this.rabbitTemplate.convertSendAndReceive(msg);
//         this.rabbitTemplate.converandre
         }
    
     
//     public static void main(String[] args) {
//         RabbitProducer rabbitProducer = new RabbitProducer();
//         rabbitProducer.sendSMSMessage("just for test");
//    }
     
    
}
View Code

 

 

方式二  : topic

配置:

package com.icil.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class RabbitConfig2 {
    
    /********************************topic****************************************/
    
    
    @Bean
    public TopicExchange topicExchange() {
        /**
         * TopicExchangeName
         * 是否持久化
         * 是否自动删除
         */
        return new TopicExchange("topicExchange", true, false);
    }
    
    /**
     * 创建一个队列,指定一个Exchange
     * @return
     */
    @Bean
    public Queue topicQueue01() {
        return QueueBuilder.durable("topicExchange01").build();
    }
    
    @Bean
    public Queue topicQueue02() {
        return QueueBuilder.durable("topicExchange02").build();
    }
    
    
       @Bean
        public Binding binding() {
            return BindingBuilder.bind(topicQueue01()).to(topicExchange()).with("A.#");
        }
        @Bean
        public Binding binding2() {
            return BindingBuilder.bind(topicQueue02()).to(topicExchange()).with("#.B.#");
        }
        
        
    
    
    
//    @Bean
//    public Binding bindingtopic(@Qualifier("topicQueue") Queue queue, DirectExchange exchange) {
//        return BindingBuilder.bind(queue).to(exchange).with("A.B.C"); }
    
    
}
View Code

 

发送消息

package com.icil.rabbitmq;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class RabbitProducer002 implements ConfirmCallback , ReturnCallback{

    private  static Logger  log =LoggerFactory.getLogger(RabbitProducer002.class);
    
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    
    
    
    
     /** * 初始化确认发送回调及发送返回回调 */ 
    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
        }
    
    
      /**
     * 实现消息发送到RabbitMQ交换器后接收ack回调
     * @param correlationData
     * @param ack
     * @param cause
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        
         if (ack){ 
              // 发送成功 
             log.info("trainLink message send success################## 888---"+System.currentTimeMillis() ); 
             
             log.info("cause  is################## ---",cause );
              } else { // 发送失败
                 log.error("trainLink message send failed because ---" + cause); 
             }
    }
    
    
    
    
/**
 *  * 实现消息发送到RabbitMQ交换器,但无相应队列与交换器绑定时的回调 
 *  * @param message
 *  * @param replyCode 
 *  * @param replyText 
 *  * @param exchange 
 *  * @param routingKey
 */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        
        log.info("$$$$$$$$$$$$$$$$$$$$$$$  message is {}  $$$   replyCode is {}   $$$  replyText is {}  $$$   exchange is {}   $$$ and routingKey is {}",message,replyCode, replyText,exchange,routingKey);
//          log.error(message.getMessageProperties().getCorrelationIdString() + " send failed:error code " + replyCode + "mains:" + replyText);
         log.error(message.getMessageProperties().getClusterId() + " send failed:error code " + replyCode + "mains:" + replyText);
         
    }

    
     /** 
      * * 发送消息,供外部调用 
      * * ****** 重要 ******说明:发送时的方法选择 
      * * ****** 重要 ******convertAndSend属于不要求返回确认的 
      * * ****** 重要 ******convertSendAndReceive要求返回确认 
      * * ****** 重要 ******大家根据不同的业务场景进行选择, 
      * * 不返回确认可以理解为全异步; 
      * * 返回确认可以理解为异步处理,同步返回,存在一个生产者等待消费者的问题 
      * * 选择的原则一般为一致性要求较强的,要确认返回; 
      * * 一致性不强的,使用不返回确认,加大处理效率,免去等待时间 */
    
     public void sendSMSMessage(String msg){
     // fanout类型的交换器不需要routingkey,我这里用的是direct所以指定了对应的routingkey 
     this.rabbitTemplate.convertAndSend("topicExchange", "A.B.key", msg); 
     }

     
    
}
View Code

/*********************************************************************/

 

接受消息: (依赖与上面一样,无需其他配置)

  配置yml  

spring:
  rabbitmq:
#    host: 192.168.18.129
    addresses: 192.168.18.129:5672
    username: root
    password: root
#    支持发布确认
    publisher-confirms: true
#    支持发布返回
    publisher-returns: true
    listener:
      simple:
#        监听的最小线程数
        concurrency: 4
#        监听的最大线程数
        max-concurrency: 8
        retry:
          enabled: true
#         ack应答改模式:auto-自动,manual-手动,none-无应答
        acknowledge-mode: auto

 

接收消息:(使用注解 --也可不用,此处用注解)

 

方式一:注解  可以参考 :https://www.jianshu.com/p/382d6f609697

package com.icil.rabbitmq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.Channel;


@Component
public class RabbitMQConsumer {
    private  static Logger  log =LoggerFactory.getLogger(RabbitMQConsumer.class);
    /**
     * * 消费者处理接收消息方法 *
     * <p>
     * * ****重要说明***** * 如果生产者是以convertSendAndReceive方法发送,则一定要手动给予返回,处理完后加入下面这一行: *
     * ack-true处理:channel.basicAck(message.getMessageProperties().getDeliveryTag(),
     * false); * 参数说明-------消息id,fasle代表不批量处理(批量是指将消息id小于当前id的都处理掉) *
     * ack-false处理:channel.basicNack(message.getMessageProperties().getDeliveryTag(),
     * false, false); *
     * 参数说明-------消息id,fasle代表不批量处理(批量是指将消息id小于当前id的都处理掉),第二个false表示不重新入队(重新入队用true)
     * * 拒绝消息:channel.basicReject(message.getMessageProperties().getDeliveryTag(),
     * false); 消息不会重新入队 * 参数说明-------消息id,fasle表示不重新入队(重新入队用true) *
     * 如果不手动返回,则该消息会一直认为没有被消费掉,会一直占用rabbitmq内存空间,时间一久,必然造成内存溢出,切记!!! * * @param msg
     * * @param message * @param channel * @throws Exception
     */
   
    
    //支持自动声明绑定,声明之后自动监听队列的队列,此时@RabbitListener注解的queue和bindings不能同时指定,否则报错
//    @RabbitListener(bindings ={@QueueBinding(value = @Queue(value = "q5",durable = "true"),
//            exchange =@Exchange(value = "zhihao.miao.exchange",durable = "true"),key = "welcome")})


    
//    @RabbitListener(queues = "name")
//   @RabbitListener(queues = {"name","topicExchange01","topicExchange02"})
//    public void handler(String msg, Message message, Channel channel) throws Exception {
//        try {
//            System.out.println("$$$$$$$$$$$$$$$$$$$$$$"+msg);
//        } catch (Exception e) {
//            log.error(e.toString(), e);
//            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
//        }
//    }
   
   @RabbitListener(queues = {"topicExchange01"})
      public void handler1(String msg, Message message, Channel channel) throws Exception {
          try {
              System.out.println("$$$$$$$$$$ topicExchange01 $$$$$$$$$$$$"+msg);
          } catch (Exception e) {
              log.error(e.toString(), e);
              channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
          }
      }
   
   
   @RabbitListener(queues = {"topicExchange02"})
      public void handler2(String msg, Message message, Channel channel) throws Exception {
          try {
              System.out.println("$$$$$$$$$$ topicExchange02 $$$$$$$$$$$$"+msg);
          } catch (Exception e) {
              log.error(e.toString(), e);
              channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
          }
      }
   
   @RabbitListener(queues = {"name"})
      public void handler3(String msg, Message message, Channel channel) throws Exception {
          try {
              System.out.println("$$$$$$$$$$ name $$$$$$$$$$$$"+msg);
          } catch (Exception e) {
              log.error(e.toString(), e);
              channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
          }
      }
   

}
View Code

 

方式二手动配置

package com.icil.config;

import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.rabbitmq.client.Channel;
@Configuration
public class Rabbitconfing {

    
    @Bean
    public CachingConnectionFactory connectionFactory(){
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses("192.168.18.129:5672");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        connectionFactory.setVirtualHost("/");
        connectionFactory.setPublisherConfirms(true); //必须要设置
        return connectionFactory;
    }
    
    
    
    
    @Bean
    public TopicExchange topicExchange() {
        /**
         * TopicExchangeName
         * 是否持久化
         * 是否自动删除
         */
        return new TopicExchange("topicExchange", true, false);
    }
    
    
    @Bean
    public Queue topicQueue01() {
        return QueueBuilder.durable("topicExchange01").build();
    }
    
    @Bean
    public Queue topicQueue02() {
        return QueueBuilder.durable("topicExchange02").build();
    }
    
    
    
    
//   @Bean
//    public Binding binding() {
//        return BindingBuilder.bind(topicQueue01()).to(topicExchange()).with("A.key");
//    }
//    @Bean
//    public Binding binding2() {
//        return BindingBuilder.bind(topicQueue02()).to(topicExchange()).with("B.C");
//    }
//        
        
    
    
    
    
    
    
    
    
    
    
    
    @Bean
    public SimpleMessageListenerContainer messageContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
        
        
        container.setQueues(topicQueue01());
        container.setExposeListenerChannel(true);
        container.setMaxConcurrentConsumers(1);
        container.setConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.AUTO); //设置确认模式手工确认
        container.setMessageListener(new ChannelAwareMessageListener() {
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                byte[] body = message.getBody();
                          System.out.println("¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥receive msg queue: " + new String(body));
//                          Thread.sleep(10000);

                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费

            }

        

        
        });
        return container;
    }
    
    

    @Bean
    public SimpleMessageListenerContainer messageContainer2() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
        container.setQueues(topicQueue02());
        container.setExposeListenerChannel(true);
        container.setMaxConcurrentConsumers(1);
        container.setConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
        container.setMessageListener(new ChannelAwareMessageListener() {
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                byte[] body = message.getBody();
                System.out.println("¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥key: " + new String(body));
//                Thread.sleep(10000);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费


            }
        });
        return container;
    }
    
    
    
    
    
    
    
    
    
}
View Code

 

posted on 2018-11-13 14:32  lshan  阅读(177)  评论(0编辑  收藏  举报