RabbitMQ-Spring整合

目录

Spring-boot中通过注解封装RabbitMQ的使用。

Spring通过XML配置使用rabbitMQ。


通过前面的RabbitMQ的java应用,我们初步了解到MQ的使用。在实际中,我们基本上都不需要这么用,可以直接通过把rabbitMQ整合Spring中,spring帮我们封装了一些消息者、生产者的功能,我们可以直接使用。

 

Spring-boot中通过注解封装RabbitMQ的使用。

1.添加依赖pom.xml

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

2.配置服务器、用户、密码application.properties

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5673
spring.rabbitmq.username=root
spring.rabbitmq.password=root
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.publisher-returns=true

3.通过注解定义队列、交换器等。

package mytest.springboot.myRabbitMQTest.common;

import java.util.HashMap;
import java.util.Map;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;

import mytest.springboot.myRabbitMQTest.common.producer.MyConfirmCallback;
import mytest.springboot.myRabbitMQTest.common.producer.MyReturnCallBack;

/**
 * RabbitMQ 配置
 */
@Configuration
public class RabbitMQConfig {

	@Bean
	RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
		return new RabbitAdmin(connectionFactory);
	}

	@Bean
	Queue queueFooDead(RabbitAdmin rabbitAdmin) {
		Queue queue = new Queue("queue.fooErr", true,true, false);
		rabbitAdmin.declareQueue(queue);
		return queue;
	}

	@Bean
	FanoutExchange deadExchange(RabbitAdmin rabbitAdmin) {
		FanoutExchange deadExchange = new FanoutExchange("deadExchange");
		rabbitAdmin.declareExchange(deadExchange);
		return deadExchange;
	}

	@Bean
	Binding bindingExchangeFooDead(Queue queueFooDead, FanoutExchange deadExchange, RabbitAdmin rabbitAdmin) {
		Binding binding = BindingBuilder.bind(queueFooDead).to(deadExchange);
		rabbitAdmin.declareBinding(binding);
		return binding;
	}

	@Bean
	Queue queueFoo(RabbitAdmin rabbitAdmin) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("x-dead-letter-exchange", "deadExchange");// 设置死信交换机
		map.put("x-dead-letter-routing-key", "mail_queue_fail");// 设置死信routingKey
		Queue queue = new Queue("queue.foo", true, false, false, map);
		rabbitAdmin.declareQueue(queue);
		return queue;
	}

	@Bean
	Queue queueBar(RabbitAdmin rabbitAdmin) {
		Queue queue = new Queue("queue.bar", true);
		rabbitAdmin.declareQueue(queue);
		return queue;
	}

	@Bean
	TopicExchange exchange(RabbitAdmin rabbitAdmin) {
		TopicExchange topicExchange = new TopicExchange("exchange");
		rabbitAdmin.declareExchange(topicExchange);
		return topicExchange;
	}

	@Bean
	Binding bindingExchangeFoo(Queue queueFoo, TopicExchange exchange, RabbitAdmin rabbitAdmin) {
		Binding binding = BindingBuilder.bind(queueFoo).to(exchange).with("queue.foo");
		rabbitAdmin.declareBinding(binding);
		return binding;
	}

	@Bean
	Binding bindingExchangeBar(Queue queueBar, TopicExchange exchange, RabbitAdmin rabbitAdmin) {
		Binding binding = BindingBuilder.bind(queueBar).to(exchange).with("queue.bar");
		rabbitAdmin.declareBinding(binding);
		return binding;
	}

	/**
	 * 生产者用
	 * 
	 * @return
	 */
	@Bean
	public RabbitMessagingTemplate rabbitMessagingTemplate(RabbitTemplate rabbitTemplate) {
		RabbitMessagingTemplate rabbitMessagingTemplate = new RabbitMessagingTemplate();
		rabbitMessagingTemplate.setMessageConverter(jackson2Converter());
		rabbitMessagingTemplate.setRabbitTemplate(rabbitTemplate);
		// 消息发送失败返回到队列中, yml需要配置 publisher-returns: true
		rabbitTemplate.setMandatory(true);
		// 消息返回, yml需要配置 publisher-returns: true
		rabbitTemplate.setReturnCallback(new MyReturnCallBack()); // 消息最终没有进行队列时回调
		// 消息确认, yml需要配置 publisher-confirms: true
		rabbitTemplate.setConfirmCallback(new MyConfirmCallback());// 消息保存成功后回调
		return rabbitMessagingTemplate;
	}

	@Bean
	public MappingJackson2MessageConverter jackson2Converter() {
		MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
		return converter;
	}

}
package mytest.springboot.myRabbitMQTest.common.consumer;

import java.io.IOException;
import java.util.Random;

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

import mytest.springboot.myRabbitMQTest.Vo.Bar;
import mytest.springboot.myRabbitMQTest.Vo.Foo;
import com.rabbitmq.client.Channel;

@Component
public class ReceiverService {

    //消费者
	@RabbitListener(queues = "queue.bar")
	public void receiveBarQueue(Bar bar) {
		System.out.println("Received Bar<" + bar.getAge() + ">");
	}

}

生产者

package mytest.springboot.myRabbitMQTest.common.producer;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
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;

import mytest.springboot.myRabbitMQTest.Vo.Bar;
import mytest.springboot.myRabbitMQTest.Vo.Foo;

@Component
public class SenderService {


	@Autowired
	private RabbitTemplate rabbitTemplate;

	public void sendFoo2RabbitmqByRabbitTemplate(final Foo foo) {

		System.out.println("发送成功开始");
		CorrelationData correlationData = new CorrelationData();
		correlationData.setId("12345678911111111111");
		this.rabbitTemplate.convertAndSend("exchange", "queue.foo", foo ,correlationData);
		System.out.println("发送成功完成1");
		CorrelationData correlationData2 = new CorrelationData();
		correlationData2.setId("12345678911111111112");
		this.rabbitTemplate.convertAndSend("exchange", "queue.foo", foo ,correlationData2);//异步方法
		System.out.println("发送成功完毕");


	}

}

Spring通过XML配置使用rabbitMQ。

  1. 通过Maven加入Spring与RabbitMQ的依赖。
    <!--rabbitmq依赖 -->  
    <dependency>  
        <groupId>org.springframework.amqp</groupId>  
        <artifactId>spring-rabbit</artifactId>  
        <version>1.3.5.RELEASE</version>  
    </dependency>  
  2. 通过Spring配置rabbit:connection-factory、rabbit:admin、队列、rabbit:template消息模板、交换器(绑定的队列)、消费端、生产端

      以下是XML方式配置

<!-- 消费端配置 ********************************************** -->
	<!--配置connection-factory,指定连接rabbit server参数 -->
	<rabbit:connection-factory id="connectionFactory" virtual-host="/" username="${rabbitmq.user}" password="${rabbitmq.password}"
		host="${rabbitmq.ip}" port="${rabbitmq.port}" />
	<!-- username="root" password="root" host="127.0.0.1" -->

	<!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
	<rabbit:admin id="connectAdmin" connection-factory="connectionFactory" />

	<!--定义queue -->
	<rabbit:queue name="queue1" durable="true" auto-delete="false" exclusive="false" declared-by="connectAdmin" />

	<!-- 定义direct exchange,绑定queue1 -->
	<rabbit:direct-exchange name="exchange1"
		durable="true" auto-delete="false" declared-by="connectAdmin">
		<rabbit:bindings>
			<rabbit:binding queue="queue1" key="keys"></rabbit:binding>
		</rabbit:bindings>
	</rabbit:direct-exchange>

	<!--定义rabbit template用于数据的接收和发送 -->
	<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" exchange="exchange1" />

	<!-- 消息接收者 (消费者) ,自动确认-->
	<bean id="messageReceiver" class="test.rabbitmq.MessageConsumer"></bean>
	
	<!-- 消息接收者 (消费者),需要手功确认 -->
	<bean id="ackMessageReceiver" class="test.rabbitmq.AckMessageConsumer"></bean>

	<!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象 -->
	<rabbit:listener-container  connection-factory="connectionFactory" > 
		<rabbit:listener queues="queue1" ref="messageReceiver" />
	</rabbit:listener-container> 

    <!--<rabbit:listener-container
		connection-factory="connectionFactory" acknowledge="manual">
		<rabbit:listener queues="queue1" ref="ackMessageReceiver" />
	</rabbit:listener-container> -->
	<!-- 消费端配置 end*************** ******************* -->


<!-- 生产端 , 不需要确认-->
	<rabbit:template id="amqpSendTemplate" connection-factory="connectionSendFactory" exchange="exchange1" />
		
	<bean id="messageProducer" class="test.rabbitmq.MessageProducer">
		<property name="amqpTemplate">
			<ref bean="amqpSendTemplate" />
		</property>
	</bean>
	
	<!-- 生产端 ,带确认-->
	<rabbit:template id="amqpSendTemplateRabbit" connection-factory="connectionSendFactory" exchange="exchange1" 
		confirm-callback="confirmCallBackListener"   return-callback="returnCallBackListener" mandatory="true" />
        
	<bean id="messageProducerAck" class="test.rabbitmq.MessageRabbitProducer">
		<property name="amqpTemplate">
			<ref bean="amqpSendTemplateRabbit" />
		</property>
	</bean>
	
	<bean id="confirmCallBackListener"
		class="test.rabbitmq.ConfirmCallBack">
	</bean>
	<bean id="returnCallBackListener"
		class="test.rabbitmq.ReturnCallBack">
	</bean>
  1. 实现MessageListener接口的MessageConsumer类跟实现ChannelAwareMessageListener(支持手动应答)类 AckMessageConsumer 进行队列消费的消费。
    package test.rabbitmq;
    
    import java.io.UnsupportedEncodingException;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.amqp.core.Message;
    import org.springframework.amqp.core.MessageListener;
    
    public class MessageConsumer implements MessageListener {
    	private Logger logger = LoggerFactory.getLogger(MessageConsumer.class);
    
    	@Override
    	public void onMessage(Message message) {
    		logger.info("consumer receive message------->:{}", message);
    		String message1;
    		try {
    			message1 = new String(message.getBody(), "UTF-8");
    			logger.info("consumer receive message------->:{}",message1 );
    
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    	}
    
    }
    package com.sinosig.sgis.cls.common.rabbitmq;
    
    import java.io.UnsupportedEncodingException;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.amqp.core.Message;
    import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
    
    import com.rabbitmq.client.Channel;
    
    public class AckMessageConsumer implements ChannelAwareMessageListener{
    	private Logger logger = LoggerFactory.getLogger(MessageConsumer.class);
    	
    	@Override
    	public void onMessage(Message message, Channel arg1) throws Exception {
    		
    		logger.info("ACK consumer receive message------->:{}", message);
    		String message1;
    		try {
    			message1 = new String(message.getBody(), "UTF-8");
    			logger.info("ACK consumer receive message------->:{}",message1 );
    
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		Thread.sleep(10000);
    		logger.info("ACK END");
    		//消费确认
    		arg1.basicAck(message.getMessageProperties().getDeliveryTag(), true);
    		
    		//消费拒绝
    //		logger.info("ACK REJECT");
    //		arg1.basicReject(message.getMessageProperties().getDeliveryTag(), true); //第二个参数表示放回原消息队列
    
    	}
    
    }
    

    2.配置rabbit:template模板,配置AmqpTemplate 进行消息的生产,配置实现ConfirmCallback接口进行消息发送的确认。

    package test.rabbitmq;
    
    import java.io.IOException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.amqp.core.AmqpTemplate;
    
    
    public class MessageProducer {
        private Logger logger = LoggerFactory.getLogger(MessageProducer.class);  
    
        private AmqpTemplate amqpTemplate;  
        public AmqpTemplate getAmqpTemplate() {
    		return amqpTemplate;
        }
    	public void setAmqpTemplate(AmqpTemplate amqpTemplate) {
    		this.amqpTemplate = amqpTemplate;
    	}
    
    
    	public void sendMessage(Object message) throws IOException {  
            logger.info("to send message:{}", message);  
            
            //u普通生产消息 
            amqpTemplate.convertAndSend("keys", message);
            
        }  
    }
    package test.rabbitmq;
    
    import java.io.IOException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.amqp.core.AmqpTemplate;
    
    public class MessageRabbitProducer {
    
    	private Logger logger = LoggerFactory.getLogger(MessageProducer.class);
    
    	private AmqpTemplate amqpTemplate;
    
    	public AmqpTemplate getAmqpTemplate() {
    		return amqpTemplate;
    	}
    
    	public void setAmqpTemplate(AmqpTemplate amqpTemplate) {
    		this.amqpTemplate = amqpTemplate;
    	}
    
    	public void sendMessage(Object message) throws IOException {
    		logger.info("to send message:{}", message);
    		amqpTemplate.convertAndSend("keys", message);
    		amqpTemplate.convertAndSend("keys1111", message);
    
    	}
    }
    package test.rabbitmq;
    
    import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
    import org.springframework.amqp.rabbit.support.CorrelationData;
    
    public class ConfirmCallBack implements ConfirmCallback {
    	
    	@Override
    	public void confirm(CorrelationData correlationData, boolean ack) {
    		System.out.println("confirm--:correlationData:" + correlationData + ",ack:" + ack + ",cause:" );
    		
    	}
    }
    package test.rabbitmq;
    
    import org.springframework.amqp.core.Message;
    import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback;
    
    public class ReturnCallBack implements ReturnCallback {
    	@Override
    	public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
    		System.out.println("return--message:" + new String(message.getBody()) + ",replyCode:" + replyCode
    				+ ",replyText:" + replyText + ",exchange:" + exchange + ",routingKey:" + routingKey);
    	}
    }

     

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值