Spring RabbitMQ - использование ручного подтверждения канала на службе с конфигурацией @RabbitListener
как отметить сообщения вручную, без использования автоматического подтверждения. 
Есть ли способ использовать это вместе с @RabbitListener и @EnableRabbit стиль конфигурации. 
Большая часть документации говорит нам использовать SimpleMessageListenerContainer вместе с ChannelAwareMessageListener. 
Однако, используя это, мы теряем гибкость, которая предоставляется с аннотациями. 
Я настроил свой сервис, как показано ниже:
@Service
public class EventReceiver {
@Autowired
private MessageSender messageSender;
@RabbitListener(queues = "${eventqueue}")
public void receiveMessage(Order order) throws Exception {
  // code for processing order
}
мой RabbitConfiguration, как показано ниже
@EnableRabbit
public class RabbitApplication implements RabbitListenerConfigurer {
public static void main(String[] args) {
    SpringApplication.run(RabbitApplication.class, args);
}
@Bean
public MappingJackson2MessageConverter jackson2Converter() {
        MappingJackson2MessageConverter converter = new  MappingJackson2MessageConverter();
        return converter;
    @Bean
public SimpleRabbitListenerContainerFactory myRabbitListenerContainerFactory() {
      SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
      factory.setConnectionFactory(rabbitConnectionFactory());
      factory.setMaxConcurrentConsumers(5);
      factory.setMessageConverter((MessageConverter) jackson2Converter());
      factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
      return factory;
    }
@Bean
public ConnectionFactory rabbitConnectionFactory() {
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
    connectionFactory.setHost("localhost");
    return connectionFactory;
}
@Override
public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
    registrar.setContainerFactory(myRabbitListenerContainerFactory());
}
@Autowired
private EventReceiver receiver;
}
}
любая помощь будет оценили, как адаптировать ручное подтверждение канала вместе с вышеуказанным стилем конфигурации. Если мы реализуем ChannelAwareMessageListener, то подпись onMessage изменится. Можем ли мы реализовать ChannelAwareMessageListener на сервисе ?
2 ответов
добавить Channel до @RabbitListener метод...
@RabbitListener(queues = "${eventqueue}")
public void receiveMessage(Order order, Channel channel,
    @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
    ...
}
и используйте тег basicAck, basicReject.
редактировать
@SpringBootApplication
@EnableRabbit
public class So38728668Application {
    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(So38728668Application.class, args);
        context.getBean(RabbitTemplate.class).convertAndSend("", "so38728668", "foo");
        context.getBean(Listener.class).latch.await(60, TimeUnit.SECONDS);
        context.close();
    }
    @Bean
    public Queue so38728668() {
        return new Queue("so38728668");
    }
    @Bean
    public Listener listener() {
        return new Listener();
    }
    public static class Listener {
        private final CountDownLatch latch = new CountDownLatch(1);
        @RabbitListener(queues = "so38728668")
        public void receive(String payload, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag)
                throws IOException {
            System.out.println(payload);
            channel.basicAck(tag, false);
            latch.countDown();
        }
    }
}
приложение.свойства:
spring.rabbitmq.listener.acknowledge-mode=manual
Спасибо за помощь Гэри. Я, наконец, решил проблему. Я документирую это для пользы других. Это необходимо документировать как часть стандартной документации на странице справочной документации Spring AMQP. Класс обслуживания как ниже.
   @Service
    public class Consumer {
    @RabbitListener(queues = "${eventqueue}")
    public void receiveMessage(Order order, Channel channel) throws Exception {
 // the above methodname can be anything but should have channel as second signature
    channel.basicConsume(eventQueue, false, channel.getDefaultConsumer()); 
    // Get the delivery tag
    long deliveryTag = channel.basicGet(eventQueue, false).getEnvelope().getDeliveryTag();
    try {
      // code for processing order
    catch(Exception) {
     // handle exception
        channel.basicReject(deliveryTag, true);
    }
    // If all logic is successful 
    channel.basicAck(deliveryTag, false);
}
конфигурация также была изменена, как показано ниже
public class RabbitApplication implements RabbitListenerConfigurer {
    private static final Logger log = LoggerFactory.getLogger(RabbitApplication .class);
    public static void main(String[] args) {
        SpringApplication.run(RabbitApplication.class, args);
    }
    @Bean
    public MappingJackson2MessageConverter jackson2Converter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        return converter;
    }
    @Bean
    public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setMessageConverter(jackson2Converter());
        return factory;
    }
    @Autowired
    private Consumer consumer;
    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
    }
      ...
}
Примечание: нет необходимости настраивать Rabbitconnectionfactory или containerfactor и т. д., Так как имплицитность аннотации заботится обо всем этом.
