Springboot与RabbitMQ上手之简单消息监听容器和自定义消息监听(八)

前言

目的主要是学习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

你可能感兴趣的:(Springboot与RabbitMQ上手之简单消息监听容器和自定义消息监听(八))