• springboot整合ribbitMQ


    参考: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
  • 相关阅读:
    NHibernate开源框架Cuyahoga学习之数据访问实现
    Petshop4.0 缓存设计学习
    Jquery实现ToolTip之元素定位
    客户单操作Cookie
    .Net 通过MySQLDriverCS操作MySQL
    NHibernate的基本使用
    提高ASP.NET性能的十大方法
    工作流引擎下基于表达式Tree复杂验证的实现
    C#注册表操作
    WinForm应用程序中的ComboBox实现ReadOnly功能
  • 原文地址:https://www.cnblogs.com/lshan/p/9952041.html
Copyright © 2020-2023  润新知