rabbitMq实例

rabbitMq实例讲解,以springboot为主

一生产者

     1.引包

   <dependencies>
        <!-- fast json -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
         </dependency>
         <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
         </dependency>
         <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
         </dependency>
         <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-jaxb-annotations</artifactId>
         </dependency>
        
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
         </dependency>

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

 

2.配置文件

spring:

    rabbitmq:
       producer:
         addresses: 127.0.0.1:5672
         userName: developer
         password: dev0423
         publisher-confirms: true    --发布者确认
         virtual-host: dev 

 

3.RabbitMq配置文件读取类

@Configuration
@ConfigurationProperties(prefix = "spring.rabbitmq.consumer")
public class RabbitMqConfig {

    @Value("${spring.rabbitmq.consumer.addresses}")
    private String addresses;
    @Value("${spring.rabbitmq.consumer.userName}")
    private String username;
    @Value("${spring.rabbitmq.consumer.password}")
    private String password;
    @Value("${spring.rabbitmq.consumer.publisher-confirms}")
    private Boolean publisherConfirms;
    @Value("${spring.rabbitmq.consumer.virtual-host}")
    private String virtualHost;

    
    // 构建mq实例工厂
    @Bean
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(addresses);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setPublisherConfirms(publisherConfirms);
        connectionFactory.setVirtualHost(virtualHost);
        return connectionFactory;
    }

    /**
     *rabbitMq代理类
     *该类封装了对 RabbitMQ 的管理操作
     */
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        return new RabbitAdmin(connectionFactory);
    }

    /**

     * 创建rabbitTemplate 消息模板类

     * prototype原型模式:每次获取Bean的时候会有一个新的实例

     *  因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置

     * @return

     */
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate(){
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        // rabbitTemplate.setMandatory(true);//返回消息必须设置为true  
        template.setMessageConverter(jackson2JsonMessageConverter());数据转换为json          
        存入消息队列  
        //发布确认  

        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {  

        //消息发送到queue时就执行  

            @Override  

        public void confirm(CorrelationData correlationData, boolean b, String s) {  

            log.debug(correlationData+"//");  

            if (!b){  

                    log.debug("发送到queue失败");  

                    throw new RuntimeException("send error " + s);  

            }  

        }  

        });

        return template;
    }
    @Bean
    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }
}

 3.rabbitMq发送工具类

 生产者想要发送消息,首先必须要声明一个Exchange和该Exchange对应的Binding



import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class RabbitMqSender implements RabbitTemplate.ConfirmCallback{
    /** logger */
    private static final Logger logger = LoggerFactory.getLogger(RabbitMqSender.class);

    private RabbitTemplate rabbitTemplate;
    
    @Autowired
    public RabbitMqSender(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        this.rabbitTemplate.setConfirmCallback(this);
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean b, String s) {
        logger.info("confirm: " + correlationData.getId());
    }

    /**
     * 发送到 指定routekey的指定queue
     * @param routeKey
     * @param obj
     */
    public void sendRabbitmqDirect(String exchange, String routeKey, String queueName, Object obj) {
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        logger.info("send: " + correlationData.getId());
        this.rabbitTemplate.setExchange(exchange);//动态绑定
        this.rabbitTemplate.setRoutingKey(routeKey);
        RabbitAdmin admin = new RabbitAdmin(this.rabbitTemplate.getConnectionFactory());
        admin.declareQueue(new Queue(queueName));//声明队列
        DirectExchange directExchange = new DirectExchange(exchange);
        admin.declareExchange(directExchange);//声明交换机
        Binding binding = BindingBuilder.bind(new Queue(queueName)).to(directExchange).with(routeKey);//进行绑定
        admin.declareBinding(binding);
        this.rabbitTemplate.convertAndSend(exchange, routeKey , obj, correlationData);
    }

    /**
     * 所有发送到Topic Exchange的消息被转发到所有关心RouteKey中指定Topic的Queue上
     * @param routeKey
     * @param obj
     */
    public void sendRabbitmqTopic(String exchange, String routeKey, String queueName, Object obj) {
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        logger.info("send: " + correlationData.getId());
        this.rabbitTemplate.setExchange(exchange);
        this.rabbitTemplate.setRoutingKey(routeKey);
        RabbitAdmin admin = new RabbitAdmin(this.rabbitTemplate.getConnectionFactory());
        admin.declareQueue(new Queue(queueName));
        TopicExchange topicExchange = new TopicExchange(exchange);
        admin.declareExchange(topicExchange);
        Binding binding = BindingBuilder.bind(new Queue(queueName)).to(topicExchange).with(routeKey);
        admin.declareBinding(binding);
        this.rabbitTemplate.convertAndSend(exchange, routeKey , obj, correlationData);
    }
}

4.测试发送



import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;





@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableAutoConfiguration
public class TestSendMsg {

	@Autowired
	private RabbitMqSender rabbitMqSender;
	
    @Test
    public void test() {
    	boolean isTopic = true;
    	if (!isTopic) {
	    	//direct测试
	    	TUserTest user = new TUserTest("1","123456 sending message");
	    	rabbitMqSender.sendRabbitmqDirect("exchangeD","routingkeyD","queneD", user);
    	} else {
    		TUserTest user = new TUserTest("2","123456 sending topic message");
	    	rabbitMqSender.sendRabbitmqTopic("exchangeT","routingkeyT","queneT", user);
    	}
    	
    	//rabbitMqSender.sendRabbitmqTopic("exchangeT","routingkeyT", user);
    	
    	rabbitMqSender.sendRabbitmqDirect("TESTQUEUE1", "1");
    	rabbitMqSender.sendRabbitmqTopic("*.TEST.*", "2");
    	rabbitMqSender.sendRabbitmqTopic("lazy.#","3");
    	
    }
    
}

二.消费者

1.导包,与生产者一样

2.配置文件

    

spring:

    rabbitmq:
       consumer:
         addresses: 127.0.0.1:5672
         userName: developer
         password: dev0423
         publisher-confirms: true    --发布者确认
         virtual-host: dev 

3.消费者配置


import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;


@Configuration
@ConfigurationProperties(prefix = "spring.rabbitmq.consumer")
public class RabbitMqConsumerConfig {

    @Value("${spring.rabbitmq.consumer.addresses}")
    private String addresses;
    @Value("${spring.rabbitmq.consumer.userName}")
    private String username;
    @Value("${spring.rabbitmq.consumer.password}")
    private String password;
    @Value("${spring.rabbitmq.consumer.publisher-confirms}")
    private Boolean publisherConfirms;
    @Value("${spring.rabbitmq.consumer.virtual-host}")
    private String virtualHost;

    // 构建mq实例工厂,bean指定name为了防止和mq producer的冲突,下同
    @Bean(name="consumerConnectionFactory")
    public ConnectionFactory connectionFactory(){
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(addresses);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setPublisherConfirms(publisherConfirms);
        connectionFactory.setVirtualHost(virtualHost);
        return connectionFactory;
    }

    @Bean(name="consumerRabbitAdmin")
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        return new RabbitAdmin(connectionFactory);
    }

    @Bean(name="consumerRabbitTemplate")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate(){
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setMessageConverter(jackson2JsonMessageConverter());
        return template;
    }
    @Bean(name="consumerJackson2JsonMessageConverter")
    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    
}

4.配置消费者监听

   1)直联



import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.fastjson.JSON;
import com.qihai.commerce.framework.mq.consumer.RabbitMqConfig;
import com.rabbitmq.client.Channel;

/**
 * 直连消费者配置
 * 
 * @author zhugj
 * @date 2018年5月24日 下午2:03:29
 * @version 1.0.0
 */
@Configuration
@AutoConfigureAfter(RabbitMqConfig.class)
public class DirectAmqpConfiguration {
	
    @Bean("testQueueContainer")
    public MessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames("queneD");
        container.setMessageListener(listener());
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);设置确认模式手工确认,    
                    设置为手动,默认为 AUTO,如果设置了手动应答 basicack,就要设置manual
        return container;
    }


    @Bean("testQueueListener")
    public ChannelAwareMessageListener listener() {
        return new ChannelAwareMessageListener() {
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
            	String str = new String(message.getBody());
            	TUserTest userTest = null;
            	try {
            	    userTest = JSON.parseObject(str, TUserTest.class);
            	} catch (Exception e) {
            		e.printStackTrace();
            	}
                //通过设置TestUser的name来测试回调,分别发两条消息,一条UserName为1,一条为2,查看控制台中队列中消息是否被消费
                if ("1".equals(userTest.getId())){
                    System.err.println("我已经消费1成功了");
 //手动确认。消息的标识,false只确认当前一个消息收到,true确认所有consumer获得的消息 (正常消费)                   channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                }

                if ("2".equals(str)){
                    System.err.println("消息重新回到队列");
 //ack返回false,并重新回到队列,api里面解释得很清楚  (本地异常)                   channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                }

            }
        };
    }

}

2) topicjia监听类


import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.fastjson.JSON;
import com.qihai.commerce.framework.mq.consumer.RabbitMqConfig;
import com.rabbitmq.client.Channel;

/**
 * topic消费者配置
 * 
 * @author zhugj
 * @date 2018年5月24日 下午2:03:29
 * @version 1.0.0
 */
@Configuration
@AutoConfigureAfter(RabbitMqConfig.class)
public class TopicAmqpConfiguration {
    @Bean("topicTest1Container")
    public MessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames("queneT");
        container.setMessageListener(listener1());
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return container;
    }


    @Bean("topicTest1Listener")
    public ChannelAwareMessageListener listener1(){
        return new ChannelAwareMessageListener() {
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
            	String str = new String(message.getBody());
            	TUserTest userTest = null;
            	try {
            	    userTest = JSON.parseObject(str, TUserTest.class);
            	} catch (Exception e) {
            		e.printStackTrace();
            	}
            	if ("2".equals(userTest.getId())) {
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                    System.err.println("我已经消费2成功了");
            	} else if ("3".equals(userTest.getId())) { //如果有异常决定是否保留消息在队列中,basicNack是保留消息在队列中
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                    System.err.println("消息重新回到队列");
            	}

            }
        };
    }

}

 

参考文章:

RabbitMq写的比较好的:https://www.cnblogs.com/vipstone/p/9275256.html

Springboot+rabbotMq的:https://blog.csdn.net/ztx114/article/details/78410727

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值