目录
三、 开启mq管理界面:http://localhost:15672/#/
RabbitMq实操direct方式
一、 在本地安装一个rabbitmq server:
命令行输入brew install rabbitmq即可自动安装;如果提示需要手动先安装Erlang语言环境,可以命令行输入brew install erlang先安装Erlang;
二、 启动rabbitmq服务器:
在命令行终端输入/usr/local/Cellar/rabbitmq/3.7.14/sbin/rabbitmq-server start;
三、 开启mq管理界面:http://localhost:15672/#/
四、 完成springboot项目中的代码和配置:
4.1 pom文件加入maven依赖
<!-- 集成rabbitmq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
4.2 application加入全局配置
#集成rabbitmq
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
virutalHost: /
queue: spring-queue-async
routingKey: spring-queue-async
4.3 rabbitmq的config相关代码
package org.maggiezhang.springbootdemo.common.mq;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import java.util.HashMap;
import java.util.Map;
@Configuration
@Slf4j
public class RabbitConfig {
@Value("${spring.rabbitmq.host}")
private String host;
@Value("${spring.rabbitmq.port}")
private int port;
@Value("${spring.rabbitmq.username}")
private String username;
@Value("${spring.rabbitmq.password}")
private String password;
/*direct类型的exchange*/
public static final String EXCHANGE_DIRECT_A = "my-mq-exchange_direct_A";
public static final String EXCHANGE_DIRECT_B = "my-mq-exchange_B";
public static final String EXCHANGE_DIRECT_C = "my-mq-exchange_C";
public static final String QUEUE_DIRECT_A = "QUEUE_DIRECT_A";
public static final String QUEUE_DIRECT_B = "QUEUE_DIRECT_B";
public static final String QUEUE_DIRECT_C = "QUEUE_DIRECT_C";
public static final String ROUTINGKEY_A = "spring-boot-rootingKey_A";
public static final String ROUTINGKEY_B = "spring-boot-rootingKey_B";
public static final String ROUTINGKEY_C = "spring-boot-rootingKey_C";
public static int count = 1;
public static int getCount(){
return ++count;
}
/*Topic类型的exchange*/
@Bean
public ConnectionFactory connectionFactory(){
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
cachingConnectionFactory.setAddresses(host+":"+port);
cachingConnectionFactory.setUsername(username);
cachingConnectionFactory.setPassword(password);
cachingConnectionFactory.setVirtualHost("/");
cachingConnectionFactory.setPublisherConfirms(true);
return cachingConnectionFactory;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate(){
RabbitTemplate template=new RabbitTemplate((connectionFactory()));
return template;
}
/**
* 针对消费者配置
* 1. 设置交换机类型
* 2. 将队列绑定到交换机
FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
HeadersExchange :通过添加属性key-value匹配
DirectExchange:按照routingkey分发到指定队列
TopicExchange:多关键字匹配
*
* @return
*/
@Bean
public DirectExchange defaultExchangeA(){
return new DirectExchange(EXCHANGE_DIRECT_A);
}
/**
* 获取队列A
* @return
*/
@Bean
public Queue queueA(){
return new Queue(QUEUE_DIRECT_A, true);
}
/**
* 获取队列B
* @return
*/
@Bean
public Queue queueB(){
return new Queue(QUEUE_DIRECT_B, true);
}
/**
* routingkey_A using: exchange_A and queue_A
* @return
*/
@Bean
public Binding binding(){
return BindingBuilder.bind(queueA()).to(this.defaultExchangeA()).with(RabbitConfig.ROUTINGKEY_A);
}
/**
* routingkey_B using: exchange_A and queue_A
* @return
*/
@Bean
public Binding bindingA(){
return BindingBuilder.bind(queueA()).to(this.defaultExchangeA()).with(RabbitConfig.ROUTINGKEY_B);
}
/**
* routingkey_B using: exchange_A and queue_B
* @return
*/
@Bean
public Binding bindingB(){
return BindingBuilder.bind(queueB()).to(this.defaultExchangeA()).with(RabbitConfig.ROUTINGKEY_B);
}
/**
* 接收message写法二:使用SimpleMessageListenerContainer
*
* */
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(){
SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer(connectionFactory());
simpleMessageListenerContainer.setQueues(queueB());
simpleMessageListenerContainer.setExposeListenerChannel(true);
simpleMessageListenerContainer.setMaxConcurrentConsumers(10);
simpleMessageListenerContainer.setConcurrentConsumers(2);
simpleMessageListenerContainer.setAcknowledgeMode(AcknowledgeMode.MANUAL);
//后置处理器,接收到的消息都添加了Header请求头
/*simpleMessageListenerContainer.setAfterReceivePostProcessors(message -> {
message.getMessageProperties().getHeaders().put("desc",10);
return message;
});
//设置消费者的consumerTag_tag
simpleMessageListenerContainer.setConsumerTagStrategy(queue -> "order_queue_"+(++count));
//设置消费者的Arguments
Map<String, Object> args = new HashMap<>();
args.put("module","订单模块");
args.put("fun","发送消息");
simpleMessageListenerContainer.setConsumerArguments(args);*/
simpleMessageListenerContainer.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
channel.basicQos(1);
byte[] body=message.getBody();
log.info("---------监听并处理队列B中的消息:"+new String(body));
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
});
return simpleMessageListenerContainer;
}
}
4.4 生产者代码
package org.maggiezhang.springbootdemo.common.mq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Slf4j
@Service
public class MsgProducerA implements RabbitTemplate.ConfirmCallback {
//由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自动注入
private RabbitTemplate rabbitTemplate;
@Autowired
public MsgProducerA(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setConfirmCallback(this);//rabbitTemplate如果为单例的话,那回调就是最后设置的内容
}
public void sendMsgWithRoutingkeyA(String content){//default is queueA
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
//把消息放入ROUTINGKEY_A对应的队列当中去,对应的是队列A
rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_DIRECT_A, RabbitConfig.ROUTINGKEY_A, content, correlationId);
}
public void sendMsgWithRoutingkeyB(String content){
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
//把消息放入ROUTINGKEY_B对应的队列当中去,对应的是队列A和队列B,所以队列A和队列B将会同时收到消息
rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_DIRECT_A, RabbitConfig.ROUTINGKEY_B, content, correlationId);
}
/**
* 回调
* @param correlationData
* @param ack
* @param cause
*/
@Override
public void confirm(@Nullable CorrelationData correlationData, boolean ack, @Nullable String cause) {
log.info("回调id:"+correlationData);
//log.info(correlationData.getReturnedMessage());
if(ack){
log.info("。。。消息成功消费");
}else{
log.info("。。。消息消费失败"+cause);
}
}
}
4.5 消费者代码
package org.maggiezhang.springbootdemo.common.mq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.annotation.RabbitListeners;
import org.springframework.stereotype.Component;
/**
* 接收message写法一:使用RabbitListener
*
* */
@Component
@RabbitListener(queues = RabbitConfig.QUEUE_DIRECT_A)
@Slf4j
public class MsgReceiverDirectQueueA {
@RabbitHandler
public void process(String content){
log.info("接收处理队列A当中的消息:" + content);
}
}
4.6 测试代码
package org.maggiezhang.springbootdemo.common;
import lombok.extern.slf4j.Slf4j;
import org.maggiezhang.springbootdemo.CaseBase;
import org.maggiezhang.springbootdemo.common.mq.MsgProducerA;
import org.maggiezhang.springbootdemo.common.mq.RabbitConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.Test;
import java.util.Date;
@Slf4j
public class TestMsgProducerA extends CaseBase{
@Autowired
MsgProducerA msgProducerA;
@Test
public void testSend_DIRECTMsgA(){
log.info("...testSendMsgA");//routingkey_A
msgProducerA.sendMsgWithRoutingkeyA("这是A发送的消息"+ new Date());
log.info("这是A发送的消息"+ new Date());
}
@Test
public void testSend_DIRECTMsgB(){//routingkey_B
log.info("...testSendMsgB");
msgProducerA.sendMsgWithRoutingkeyB("这是B发送的消息"+ new Date());
log.info("这是B发送的消息"+ new Date());
}
}