目录
一:springboot2.x整合rabbitmq
1.maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
2.yml配置
spring.application.name=springboot-rabbitmq
# ip
spring.rabbitmq.host=192.168.72.131
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
spring.rabbitmq.virtual-host=/
spring.rabbitmq.listener.direct.acknowledge-mode=manual
二:6种工作模式
1.helloword模式(一对一模式)
(1)添加配置
package com.rabbitmq.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.rabbitmq.constant.MqConstant;
/**
* hellowrod-模式:一对一,配置一个队列即可
* @author monxz
*
*/
@Configuration
public class RabbitMqForHelloWordConfig {
@Bean
public Queue queueHwWork1() {
//MqConstant.hello_word_name = "queue-hello-word"
return new Queue(MqConstant.hello_word_name);
}
}
(2)添加监听消费者
package com.rabbitmq.customer;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
import com.rabbitmq.constant.MqConstant;
/**
* work模式消费者
* @author monxz
*
*/
@Component
public class helloWordCustmer {
@RabbitListener(queues = MqConstant.hello_word_name)
//hello_word_name="queue-hello-word"
public void receiveMessage(String msg, Channel channel, Message message) {
// 只包含发送的消息
System.out.println("1接收到消息:" + msg);
}
}
(3)添加生产者
@Resource
private RabbitTemplate rabbitTemplate ;
@GetMapping("/hello")
private Object testHelloWord() {
for(int i = 0 ; i < 10 ; i++) {
rabbitTemplate.convertAndSend(MqConstant.hello_word_name,"work测试:"+i);
}
return "sussess";
}
2.work模式(一对多)
work模式是最简单的一对多的应用模型,其使用多个队列监听一个队列(即生产者感觉自己只发送了数据到单个队列,消费者开启多个队列监听)但是数据只能消费一次,不会产生重复消费, 其实则模型为:
(1)配置代码
package com.rabbitmq.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.rabbitmq.constant.MqConstant;
/**
* Work模式:多用于高并发情况下,请求分流
* @author monxz
*
*/
@Configuration
public class RabbitMqForWorkConfig {
// 配置一个工作模型队列
@Bean
public Queue queueWork1() {
return new Queue(MqConstant.work_queue_name);
}
}
(2)消费者配置
package com.rabbitmq.customer;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
import com.rabbitmq.constant.MqConstant;
/**
* work模式消费者
* @author monxz
*
*/
@Component
public class WorkCustmer {
@RabbitListener(queues = MqConstant.work_queue_name)
public void receiveMessage(String msg, Channel channel, Message message) {
// 只包含发送的消息
System.out.println("1接收到消息:" + msg);
// channel 通道信息
// message 附加的参数信息
}
@RabbitListener(queues = MqConstant.work_queue_name)
public void receiveMessage2(String obj, Channel channel, Message message) {
// 包含所有的信息
System.out.println("2接收到消息:" + obj);
}
}
(3)生产者
@Resource
private RabbitTemplate rabbitTemplate ;
@GetMapping("/work")
private Object testWork() {
for(int i = 0 ; i < 10 ; i++) {
//convertAndSend效果类似异步发送,不会管消费端的处理
rabbitTemplate.convertAndSend(MqConstant.work_queue_name,"work测试:"+i);
//convertSendAndReceive效果类似同步发送,消费端消费掉当前的消费(ACK),才会发送下一条消息
// rabbitTemplate.convertSendAndReceive(MqConstant.work_queue_name,"work测试:"+i);
}
return "sussess";
}
3.Direct模式(路由模式)
路由模式,是由一个交换机绑定多个队列,每一个队列通过一个key值取匹配。因此生产者发送消息需要指定交换机,队列的key。其模型为:
(1)配置
package com.rabbitmq.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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.rabbitmq.constant.MqConstant;
/**
* Direct路由模式 完全匹配参数,发送到对应队列
* @author monxz
*
*/
@Configuration
public class RabbitMqForDirectConfig {
//
@Bean
public Queue queueDirect1() {
return new Queue(MqConstant.derect_queue_name_01);
}
//
@Bean
public Queue queueDirect2() {
return new Queue(MqConstant.derect_queue_name_02);
}
// 准备一个交换机
@Bean
public DirectExchange exchangeDtFanout() {
return new DirectExchange (MqConstant.derect_Exchange_name);
}
// 将交换机和队列进行绑定
@Bean
public Binding bindingDtExchange1() {
//路由d1发送到这里
return BindingBuilder.bind(queueDirect1()).to(exchangeDtFanout()).with("d1");
}
@Bean
public Binding bindingDtExchange2() {
//路由d2发送到这里
return BindingBuilder.bind(queueDirect2()).to(exchangeDtFanout()).with("d2");
}
}
(2)消费者
package com.rabbitmq.customer;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.constant.MqConstant;
/**
* Topic模式消费者
* @author monxz
*
*/
@Component
public class DerectCustmer {
@RabbitListener(queues = MqConstant.derect_queue_name_01)
public void receiveMsg1(String msg) {
System.out.println("队列1接收到消息:" + msg);
}
@RabbitListener(queues = MqConstant.derect_queue_name_02)
public void receiveMsg2(String msg) {
System.out.println("队列2接收到消息:" + msg);
}
}
(3)生产者
@Resource
private RabbitTemplate rabbitTemplate ;
@GetMapping("/derect")
private Object testDerect(String key) {
for(int i = 0 ; i < 10 ; i++) {
//发布发送到匹配的队列中
rabbitTemplate.convertAndSend(MqConstant.derect_Exchange_name,key,"Topic:"+i);
}
return "sussess";
}
4.发布订阅模式
发布订阅模式是一对多模式,生产者发送一条消息,每一条消费者都会收到消息。
(1)配置
package com.rabbitmq.config;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.rabbitmq.constant.MqConstant;
import lombok.extern.slf4j.Slf4j;
/**
* 发布-订阅模式 springcloud-config配置中心实现如果使用rabbitmq实现的方式
* @author monxz
*
*/
@Configuration
@Slf4j
public class RabbitMqForPubLishConfig {
//
@Bean
public Queue queuePublish1() {
return new Queue(MqConstant.publish_queue_name_01);
}
//
@Bean
public Queue queuePublish2() {
return new Queue(MqConstant.publish_queue_name_02);
}
// 准备一个交换机
@Bean
public FanoutExchange exchangeFanout() {
return new FanoutExchange(MqConstant.publish_Exchange_name);
}
// 将交换机和队列进行绑定
@Bean
public Binding bindingExchange1() {
log.info("========================>1");
return BindingBuilder.bind(queuePublish1()).to(exchangeFanout());
}
@Bean
public Binding bindingExchange2() {
log.info("========================>2");
return BindingBuilder.bind(queuePublish2()).to(exchangeFanout());
}
}
(2)消费者
package com.rabbitmq.customer;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.constant.MqConstant;
/**
* 发布-订阅模式消费者
* @author monxz
*
*/
@Component
public class PublishCustmer {
@RabbitListener(queues = MqConstant.publish_queue_name_01)
public void receiveMsg1(String msg) {
System.out.println("队列1接收到消息:" + msg);
}
@RabbitListener(queues = MqConstant.publish_queue_name_02)
public void receiveMsg2(String msg) {
System.out.println("队列2接收到消息:" + msg);
}
}
(3)生产者
@Resource
private RabbitTemplate rabbitTemplate ;
@GetMapping("/publish")
private Object testPublish() {
for(int i = 0 ; i < 10 ; i++) {
//发布发送到对应的队列中
rabbitTemplate.convertAndSend(MqConstant.publish_Exchange_name,"","发布定于:"+i);
}
return "sussess";
}
5.topic模式
topic模式同路由模式有些相似,只不过路由模式,通过key匹配队列,topic模式通过key的通配符模式匹配队列
(1)配置
package com.rabbitmq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.rabbitmq.constant.MqConstant;
/**
* Topic模式 可以更具匹配参数,将消息发送到不同的队列中; #代表可以匹配多个单词,*只能匹配一个单词
* @author monxz
*
*/
@Configuration
public class RabbitMqForTopicConfig {
//
@Bean
public Queue queueTopic1() {
return new Queue(MqConstant.topic_queue_name_01);
}
//
@Bean
public Queue queueTopic2() {
return new Queue(MqConstant.topic_queue_name_02);
}
// 准备一个交换机
@Bean
public TopicExchange exchangeTpFanout() {
return new TopicExchange (MqConstant.topic_Exchange_name);
}
// 将交换机和队列进行绑定
@Bean
public Binding bindingTpExchange1() {
//以delete开头的消息发送到这个队列
return BindingBuilder.bind(queueTopic1()).to(exchangeTpFanout()).with("delete.#");
}
@Bean
public Binding bindingTpExchange2() {
//以update结尾的消息发送到这个队列
//以delete开头,update结尾的发送到2个队列
return BindingBuilder.bind(queueTopic2()).to(exchangeTpFanout()).with("#.update");
}
}
(2)消费者
package com.rabbitmq.customer;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.constant.MqConstant;
/**
* Topic模式消费者
* @author monxz
*
*/
@Component
public class TopicCustmer {
@RabbitListener(queues = MqConstant.topic_queue_name_01)
public void receiveMsg1(String msg) {
System.out.println("队列1接收到消息:" + msg);
}
@RabbitListener(queues = MqConstant.topic_queue_name_02)
public void receiveMsg2(String msg) {
System.out.println("队列2接收到消息:" + msg);
}
}
(3)生产者
@Resource
private RabbitTemplate rabbitTemplate ;
@GetMapping("/topic")
private Object testTopic(String key) {
for(int i = 0 ; i < 10 ; i++) {
//发布发送到匹配的队列中
rabbitTemplate.convertAndSend(MqConstant.topic_Exchange_name,key,"Topic:"+i);
}
return "sussess";
}
三
目录
:confirm和return机制
1.confirm机制
基于上面的hello-wrd模式修改,其中配置以及消费者不需要改变。生产者改变即可。
yml配置
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.publisher-confirm-type=correlated
package com.rabbitmq.service;
import javax.annotation.Resource;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import com.rabbitmq.constant.MqConstant;
@Service
public class MqService {
@Resource
private RabbitTemplate rabbitTemplate ;
/**
* 消息ACK
* @return
*/
public Object confirm() {
Object obj = "123";
rabbitTemplate.convertAndSend(MqConstant.hello_word_name,obj, new CorrelationData("" + System.currentTimeMillis()));
rabbitTemplate.setConfirmCallback(confirmCallback);
return true;
}
// 配置 confirm 机制
private final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
/**
* @param correlationData 消息相关的数据,一般用于获取 唯一标识 id
* @param b true 消息确认成功,false 失败
* @param s 确认失败的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
if (b) {
System.out.println("confirm 消息确认成功..." + correlationData.getId());
} else {
System.out.println("confirm 消息确认失败..." + correlationData.getId() + " cause: " + s);
}
}
};
}
2.return机制
return机制:是指在交换机匹配key时,找不到对应的key,数据不知道放到哪个队列中,只能返回给生产者。这里我们使用路由模式测试。
yml配置
spring.rabbitmq.publisher-returns=true
这里我们使用路由模式:
@SuppressWarnings("deprecation")
public Object returnJz() {
//设置交换机处理失败消息的模式
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
/**
*
* @param message 消息对象
* @param replyCode 错误码
* @param replyText 错误信息
* @param exchange 交换机名称
* @param routingKey 路由key
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.info("return 执行了...."+replyText);
}
});
rabbitTemplate.convertAndSend(MqConstant.derect_Exchange_name, "未知key", "什么鬼");
return true;
}