解决org.springframework.amqp.AmqpException: No method found for class [B

spring-boot在集成rabbitmq时,如果使用 amqp-client 发送消息,@RabbitListener会一直循环报错

org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method 'no match' threw exception
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:198) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:127) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1521) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1444) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1431) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1410) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:848) [spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:832) [spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:78) [spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1073) [spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_152]
Caused by: org.springframework.amqp.AmqpException: No method found for class [B
	at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getHandlerForPayload(DelegatingInvocableHandler.java:149) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.invoke(DelegatingInvocableHandler.java:129) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:60) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:190) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
	... 10 common frames omitted

通过debug发现:

rabbitTemplate.convertAndSend发送的消息默认带有消息头

而amqp-client发送的消息默认是不带消息头的

所以第一种解决办法是在rabbitmq的客户端设置响应的属性

@Test
    public void publishTest() throws IOException {
        channel.exchangeDeclare("testExchange", "direct", true);
        channel.queueBind("many", "testExchange", "many");
        String message = "this is the test";
        AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder().contentEncoding("UTF-8").contentType("text/plain").headers(new HashMap()).priority(0);
        channel.basicPublish("testExchange", "many",builder.build(), message.getBytes());
    }
测试发现问题好像是因为缺少contentType("text/plain")导致的

另外一种解决办法是在 @RabbitListener 增加一些配置

There are two conversions in the @RabbitListener pipeline.
The first converts from a Spring AMQP Message to a spring-messaging Message.
There is currently no way to change the first converter from SimpleMessageConverter which handles String, Serializable and passes everything else as byte[].
The second converter converts the message payload to the method parameter type (if necessary).
With method-level @RabbitListeners there is a tight binding between the handler and the method.
With class-level @RabbitListener s, the message payload from the first conversion is used to select which method to invoke. Only then, is the argument conversion attempted.
This mechanism works fine with Java Serializable objects since the payload has already been converted before the method is selected.
However, with JSON, the first conversion returns a byte[] and hence we find no matching @RabbitHandler.
We need a mechanism such that the first converter is settable so that the payload is converted early enough in the pipeline to select the appropriate handler method.
A ContentTypeDelegatingMessageConverter is probably most appropriate.
And, as stated in AMQP-574, we need to clearly document the conversion needs for a @RabbitListener, especially when using JSON or a custom conversion.

@Configuration
public class RabbitConfig {
    
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(new Jackson2JsonMessageConverter());
        return template;
    }

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        return factory;
    }
}
@Component
public class ReceiverTwo {

    @RabbitHandler
    @RabbitListener(queues = "test", containerFactory="rabbitListenerContainerFactory")
    public void process(String message) {
        System.out.println("Receiver: " + message);
    }
}

配置的@RabbitListeners一定要放在method-level上,否则不生效

当然,这样配置方式并不能保证Consumer端能接收到Message,所以最正确的做法是Producer端配置contentType("text/plain"),既能保证消息发送出去也能保证消息被接收。

Producer的BasicProperties配置选项如下:

解决org.springframework.amqp.AmqpException: No method found for class [B_第1张图片

你可能感兴趣的:(解决org.springframework.amqp.AmqpException: No method found for class [B)