前言
目的主要是学习RabbitMQ的SimpleMessageListenerContainer简单消息监听容器以及MessageListenerAdapter自定义消息监听,这两个基本上可以组合者使用。大概会简单介绍学习为主:毕竟还是要来演示Springboot整合RabbitMQ注解的方式来使用。
一.SimpleMessageListenerContainer简单消息监听容器
这个类对于消费端的配置项非常强大,基本可以满足的需求
- 设置同时监听多个队列、自动启动、自动配置RabbitMQ
- 设置消费数量(最大数量、最小数量、批量消费)
- 设置消息确认模式、是否重回队列、异常捕获
- 设置独占、其他消费者属性等
- 设置具体的监听器、消息转换器
- 支持动态设置,运行中修改监听器配
二.MessageListenerAdapter自定义消息监听
MessageListenerAdapter能够为消费端自定义监听接收消息,它主要分为两个模式:
- 简单模式:实现handleMessage方法,也就是该类的默认方法
- 高阶模式: 也就是自定义:Rabbitmq的队列名指定方法名来使用
2.1 自定义MessageListenerAdapter自定义消息监听
MessageListenerAdapter messageListenerAdapter =
new MessageListenerAdapter(fanoutListenerAdapter);
// 修改默认方法
// messageListenerAdapter.setDefaultListenerMethod("consumerMessage");
// HashMap
Map methodMap
= new HashMap<>(8);
// 自定义:“队列名--》》方法名”
methodMap.put("direct.queue01.test", "directListenerMethod1");
methodMap.put("fanout.queue01.test", "fanoutListenerMethod1"); messageListenerAdapter.setQueueOrTagToMethodName(methodMap);
2.2 MessageListenerAdapter默认方法
对应上面自定义的fanoutListenerAdapter类
MessageListenerAdapter messageListenerAdapter =
new MessageListenerAdapter(fanoutListenerAdapter);
里面的默认方法handleMessage
public void handleMessage(String str){
String messageBody = new String(str);
log.info("fanoutListenerMethod1:messageBody:{}", messageBody);
}
2.3 修改默认方法
对应着就是xxxxxMessage方法了
messageListenerAdapter.setDefaultListenerMethod("xxxxxMessage");
2.4 高阶用法:
Map methodMap
= new HashMap<>(8);
队列名》》》方法名:
methodMap.put("fanout.queue01.test", "fanoutListenerMethod1");
对应的方法是
public void fanoutListenerMethod1(String str){
String messageBody = new String(str);
log.info("fanoutListenerMethod1:messageBody:{}", messageBody);
}
三.消费端工程
3.1 在消费端config里面配置
SimpleMessageListenerContainer简单消息监听容器以及MessageListenerAdapter自定义消息监听
@Component
@Slf4j
public class RabbitListenerConfig {
/* 自定义MessageListenerAdapter */
@Autowired
private FanoutListenerAdapter fanoutListenerAdapter;
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setPort(5672);
connectionFactory.setPassword("guest");
connectionFactory.setUsername("guest");
connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.SIMPLE);
connectionFactory.setPublisherReturns(true);
connectionFactory.createConnection();
return connectionFactory;
}
}
@Bean
public RabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory){
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
return factory;
}
/*********************************/
// 自定义MessageListenerAdapter
/***声明 direct 队列 一对一***/
@Bean
public Exchange directExchange01() {
return new DirectExchange("dircet.exchange01.test");
}
@Bean
public Queue directQueue01() {
return new Queue("direct.queue01.test");
}
@Bean
public Binding directBinding01() {
return new Binding("direct.queue01.test",
Binding.DestinationType.QUEUE,
"dircet.exchange01.test",
"direct.queue01.key", null);
}
/***声明 fanout 队列 一对多***/
@Bean
public Exchange fanoutExchange01(){
return new FanoutExchange("fanout.exchange01.test");
}
@Bean
public Queue fanoutQueue01(){
return new Queue("fanout.queue01.test");
}
@Bean
public Binding fanoutBinding01(){
return new Binding("fanout.queue01.test",
Binding.DestinationType.QUEUE,
"fanout.exchange01.test",
"",null);
}
/**
* 配置简单 SimpleMessageListenerContainer
*/
@Bean
public SimpleMessageListenerContainer messageListenerContainer(@Autowired ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer(connectionFactory);
// 接受这个消息
container.setQueueNames("fanout.queue01.test"); // 监听队列
container.setConcurrentConsumers(1); // 当前的消费者数量
container.setMaxConcurrentConsumers(10); // 最大的消费者数量
container.setDefaultRequeueRejected(false); // 是否重回队列
container.setAcknowledgeMode(AcknowledgeMode.AUTO); // 签收模式
container.setExposeListenerChannel(true);
container.setConsumerTagStrategy(queue -> queue + "_" + UUID.randomUUID().toString());
// 第二种
// 多个channel 对应一个
container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {
log.info("message:{} ", message);
channel.basicAck(
message.getMessageProperties().getDeliveryTag(),
false
);
});
// prefetch_count参数仅仅在basic.consume的autoAck参数设置为false的前提下才生效,
// 也就是不能使用自动确认,自动确认的消息没有办法限流。
container.setPrefetchCount(10); // 限流最大
// 设置自定义MessageListenerAdapter自定义消息监听
// 1. 实现handleMessage方法
// 2. 高阶模式:自定义:“队列名--》》方法名”
MessageListenerAdapter messageListenerAdapter =
new MessageListenerAdapter(fanoutListenerAdapter);
// 修改默认方法
// messageListenerAdapter.setDefaultListenerMethod("consumerMessage");
// HashMap
Map methodMap
= new HashMap<>(8);
// 自定义:“队列名--》》方法名”
methodMap.put("direct.queue01.test", "directListenerMethod1");
methodMap.put("fanout.queue01.test", "fanoutListenerMethod1");
messageListenerAdapter.setQueueOrTagToMethodName(methodMap);
container.setMessageListener(messageListenerAdapter);
return container;
}
@Bean
public SimpleMessageListenerContainer messageListenerContainer(@Autowired ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames("fanout.queue01.test"); // 监听队列
container.setConcurrentConsumers(1); // 当前的消费者数量
container.setMaxConcurrentConsumers(10); // 最大的消费者数量
container.setDefaultRequeueRejected(false); // 是否重回队列
container.setAcknowledgeMode(AcknowledgeMode.AUTO); // 签收模式
container.setExposeListenerChannel(true);
container.setConsumerTagStrategy(queue -> queue + "_" + UUID.randomUUID().toString());
// 监听多个channel
container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {
log.info("message:{} ", message);
channel.basicAck(
message.getMessageProperties().getDeliveryTag(),
false
);
});
// prefetch_count参数仅仅在basic.consume的autoAck参数设置为false的前提下才生效,
// 也就是不能使用自动确认,自动确认的消息没有办法限流。
container.setPrefetchCount(10); // 限流最大
/************* 设置自定义MessageListenerAdapter自定义消息监听 ************/
// 1. 实现handleMessage方法
// 2. 高阶模式:自定义:“队列名--》》方法名”
MessageListenerAdapter messageListenerAdapter =
new MessageListenerAdapter(fanoutListenerAdapter);
// 修改默认方法
// messageListenerAdapter.setDefaultListenerMethod("consumerMessage");
// HashMap
Map methodMap
= new HashMap<>(8);
// 自定义:“队列名--》》方法名”
methodMap.put("direct.queue01.test", "directListenerMethod1");
methodMap.put("fanout.queue01.test", "fanoutListenerMethod1");
messageListenerAdapter.setQueueOrTagToMethodName(methodMap);
container.setMessageListener(messageListenerAdapter);
/************* 设置自定义MessageListenerAdapter自定义消息监听 ************/
return container;
}
3.2 service
@Service
@Slf4j
public class FanoutListenerAdapter {
/**
* 默认方法名
* @param str
*/
public void handleMessage(String str){
String messageBody = new String(str);
log.info("fanoutListenerMethod1:messageBody:{}", messageBody);
}
public void fanoutListenerMethod1(String str){
String messageBody = new String(str);
log.info("fanoutListenerMethod1:messageBody:{}", messageBody);
}
}
四、发送端工程
service
public interface CustomService {
// 自定义MessageListenerAdapter
public void fanoutQueue01() throws JsonProcessingException;
}
impl
必须添加
messageProperties.setContentType("text/plain");
才能让消费端接收String类参数,不则会报错接收类型错误
@Slf4j
@Service
public class CustomServiceImpl implements CustomService {
@Autowired
private RabbitTemplate rabbitTemplate;
ObjectMapper objectMapper = new ObjectMapper();
@Override
public void fanoutQueue01() throws JsonProcessingException {
/* 使用MessageProperties传递的对象转换成message*/
MessageProperties messageProperties = new MessageProperties();
// 转换成Sting 类型
messageProperties.setContentType("text/plain");
OrderMessageDTO orderMessageDTO = new OrderMessageDTO();
orderMessageDTO.setProductId(100);
orderMessageDTO.setPrice(new BigDecimal("20"));
orderMessageDTO.setOrderId(1);
String messageToSend = objectMapper.writeValueAsString(orderMessageDTO);
Message message = new Message(messageToSend.getBytes(),messageProperties);
// 发送端确认是否确认消费
CorrelationData correlationData = new CorrelationData();
// 唯一ID
correlationData.setId(orderMessageDTO.getOrderId().toString()); rabbitTemplate.convertAndSend("fanout.exchange01.test","",message,correlationData);
}
}
controller
@RestController
@Slf4j
@RequestMapping("/api/custom")
public class CustomController {
@Autowired
private CustomService customService;
@GetMapping("/fanout")
public void sendCustomFanout() throws JsonProcessingException {
customService.fanoutQueue01();
}
}
五.结语
上面就是SimpleMessageListenerContainer和MessageListenerAdapter基本入门学习,附上该之前Rabbitmq案例项目到github,
github地址:https://github.com/mi499938150/RabbitMQ-learning.git