安装:
下载地址:http://www.rabbitmq.com/install-standalone-mac.html
解压:tar zxvf rabbitmq-server-mac-standalone-3.7.14.tar.xz
基本操作命令:切换到RabbitMQ安装目录的sbin目录下,使用操作命令
启动RabbitMQ:
./rabbitmq-server restart 此命令启动不能关闭终端,关闭终端则RabbitMQ服务断开
./rabbitmq-server -detached 此命令启动关闭终端则不会影响到RabbitMQ服务
停止 RabbitMQ:./rabbitmqctl stop
可通过访问 http://localhost:15672 进行测试,默认登录账户为:guest guest
以上若不能正常访问RabbitMQ界面,则需要首先启动其管理模块
开启RabbitMQ节点:./rabbitmqctl start_app
开启RabbitMQ管理模块的插件,并配置到RabbitMQ节点上:./rabbitmq-plugins enable rabbitmq_management
关闭RabbitMQ节点:./rabbitmqctl stop
简单使用:
maven依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
配置文件
spring:application:name: spring-boot-rabbitmqrabbitmq:# 连接地址host: 127.0.0.1# 端口号,此为默认端口port: 5672# 连接用户名,默认username: guest# 连接密码,默认password: guest
消息队列
@Configurationpublic class RabbitConfig {@Beanpublic Queue queue() {//此处定义的队列名称,当此配置文件加载后此队列会加载至RabbitMQ客户端return new Queue("hellos");}}
发送者
@Slf4j@Componentpublic class HelloSender {@AutowiredAmqpTemplate amqpTemplate;public void send(String messgae) {log.info("send message: {}", messgae);//定义的队列名称需在RabbitMQ服务器中存在,需与接收者一致amqpTemplate.convertAndSend("hello", messgae);}}
接收者(下面配置了两个接收者)
@Slf4j@Component@RabbitListener(queues = "hello")public class HelloReceiver {@RabbitHandlerpublic void process(String messge) {log.info("===============HelloReceiver receiver message: {}", messge);}}@Slf4j@Component//接收消息的队列名称@RabbitListener(queues = "hello")public class HelloReceiver2 {@RabbitHandlerpublic void process(String messge) {log.info("===============HelloReceiver2 receiver message: {}", messge);}}
测试
@RunWith(SpringRunner.class)@SpringBootTestpublic class RabbitMqHelloTest {@Autowiredprivate HelloSender helloSender;/*** 单个测试** @throws Exception*/@Testpublic void hello() throws Exception {helloSender.send("测试");}/*** 多消费者** @throws Exception*/@Testpublic void oneToMany() throws Exception {for (int i = 1; i <= 10; i++) {helloSender.send(String.valueOf(i));}}}
输出:

使用交换机(Exchange):交换机的功能主要是接收消息并且转发到绑定的队列,交换机不存储消息,在启用ack模式后,交换机找不到队列会返回错误。交换机有四种类型:Direct(direct 类型的行为是"先匹配, 再投送". 即在绑定时设定一个 routing_key, 消息的routing_key 匹配时, 才会被交换器投送到绑定的队列中去), Topic(按规则转发消息(最灵活)), Headers(设置 header attribute 参数类型的交换机),Fanout(转发消息到所有绑定队列)
Direct Exchange:需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “dog”,则只有被标记为“dog”的消息才被转发,不会转发dog.puppy,也不会转发dog.guard,只会转发dog,任何发送到Direct Exchange的消息都会被转发到RouteKey中指定的Queue。
Topic Exchange:
规则配置
@Configurationpublic class TopicRabbitConfig {final static String message = "topic.message";final static String messages = "topic.messages";@Beanpublic Queue queueMessage() {return new Queue(TopicRabbitConfig.message);}@Beanpublic Queue queueMessages() {return new Queue(TopicRabbitConfig.messages);}@BeanTopicExchange exchange() {return new TopicExchange("exchange");}@BeanBinding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {//将routing_key为topic.message的通过交换机绑定到queueMessage队列return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");}@BeanBinding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {//将routing_key已topic.开头的通过交换机绑定到queueMessages队列return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");}}
发送者:通过交换机绑定不同的routing_key来实现到达不同的队列
@Slf4j@Componentpublic class TopicRabbitSender {@AutowiredRabbitTemplate rabbitTemplate;public void send1(User user){//exchange:交换机的名称;routingKey:routing_key;object:发送的数据rabbitTemplate.convertAndSend("exchange", "topic.message",user);}public void send2(User user){rabbitTemplate.convertAndSend("exchange", "topic.messages",user);}}
接收者
@Slf4j@Component@RabbitListener(queues = "topic.message")public class TopicRabbitReceiver1 {@RabbitHandlerpublic void process(User user) {log.info("=========queue topic.message receiver :{}", user.toString());}}@Slf4j@Component@RabbitListener(queues = "topic.messages")public class TopicRabbitReceiver2 {@RabbitHandlerpublic void process(User user) {log.info("=========queue topic.messages receiver :{}", user.toString());}}
测试:
@Testpublic void topic() {for (int i = 1; i <= 10; i++) {topicRabbitSender.send1(new User(Long.valueOf(i), "a"));}for (int i = 1; i <= 10; i++) {topicRabbitSender.send2(new User(Long.valueOf(i),"b" ));}}
打印测试结果:

接收方式与普通的接收方式是一致的,区别在于匹配队列
Fanout Exchange:广播模式或者订阅模式,给 Fanout 交换机发送消息,绑定了这个交换机的所有队列都收到这个消息:
规则配置
发送者:
@Configurationpublic class FanoutRabbitConfig {@Beanpublic Queue fanoutA(){return new Queue("fanoutA");}@Beanpublic Queue fanoutB(){return new Queue("fanoutB");}@BeanFanoutExchange fanoutExchange(){return new FanoutExchange("fanoutExchange");}@BeanBinding bindingFanoutExchangeA(FanoutExchange fanoutExchange,Queue fanoutA){//将队列fanoutA与fanoutExchange交换机进行绑定return BindingBuilder.bind(fanoutA).to(fanoutExchange);}@BeanBinding bindingFanoutExchangeB(FanoutExchange fanoutExchange,Queue fanoutB){//将队列fanoutB与fanoutExchange交换机进行绑定return BindingBuilder.bind(fanoutB).to(fanoutExchange);}}
@Slf4j@Componentpublic class FanoutRabbitSender {@AutowiredRabbitTemplate rabbitTemplate;public void send(String message) {//exchange:交换机的名称;routingKey:Fanout交换机无法使用routing_key,所以这里不设置routing_key;object:发送的数据rabbitTemplate.convertAndSend("fanoutExchange", "", message);}}
接收者
@Slf4j@Component@RabbitListener(queues = "fanoutA")public class FanoutRabbitReceiver1 {@RabbitHandlerpublic void process(String message) {log.info("=========queue fanoutA receiver :{}", message);}}@Slf4j@Component@RabbitListener(queues = "fanoutB")public class FanoutRabbitReceiver2 {@RabbitHandlerpublic void process(String message) {log.info("=========queue fanoutB receiver :{}", message);}}
测试:因为绑定的交换机一致,不像Topic交换机可通过routing_key区分队列,所以只要绑定此交换机的队列都会接收消息
@Testpublic void fanout(){for (int i = 1; i <= 5; i++) {fanoutRabbitSender.send("测试Fanout交换机"+i);}}





