Caused by: org.springframework.amqp.AmqpException: No method found for class [B
前言
- spring boot 2.2.13.RELEASE
错误内容:Caused by: org.springframework.amqp.AmqpException: No method found for class [B
11:06:57.392 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#6-1] WARN o.s.a.r.l.ConditionalRejectingErrorHandler - [log,129] - Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener threw exception
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.wrapToListenerExecutionFailedExceptionIfNeeded(AbstractMessageListenerContainer.java:1722)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1612)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1527)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1515)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1506)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1450)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:976)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:922)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1297)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1203)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.amqp.AmqpException: No method found for class [B
at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getHandlerForPayload(DelegatingInvocableHandler.java:151)
at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getMethodFor(DelegatingInvocableHandler.java:271)
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.getMethodFor(HandlerAdapter.java:84)
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:148)
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:135)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1608)
... 10 common frames omitted
对错误的直接理解
org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#6-1
对象中,没有适合处理 class [B
的方法。
对错误的再次理解
使用 rabbitTemplate.convertAndSend
发送的消息,默认带有消息头contentType
。spring 根据 contentType
找到适合的 处理方法处理。参考这里
我打印了一下正确的Message和错误的Message。
正确的Message(通过 rabbitTemplate.convertAndSend(RabbitConfig.MIS_EXCHANGE, RabbitConfig.MEMBER_REWARD_ROUTING, jsonObject.toString())
发出的Message):
Message :
{
"body": "eyJyZXdhcmRLZXkiOiJyZWdpc3RlciIsInRpbWUiOiIyMDIxLTA0LTA2IDExOjM3OjI0IiwidXNlcklkIjoiMSJ9",
"messageProperties": {
"consumerQueue": "member.reward",
"consumerTag": "amq.ctag-yWeKbI8-E8YILm7hlR5O4Q",
"contentEncoding": "UTF-8",
"contentLength": 0,
"contentType": "text/plain",
"deliveryTag": 1,
"finalRetryForMessageWithNoId": false,
"headers": {},
"lastInBatch": false,
"priority": 0,
"publishSequenceNumber": 0,
"receivedDeliveryMode": "PERSISTENT",
"receivedExchange": "mis.direct",
"receivedRoutingKey": "member.reward",
"redelivered": false
}
}
Message Body:
{
"rewardKey": "register",
"time": "2021-04-06 11:37:24",
"userId": "1"
}
错误的Message(通过rabbit mq 管理后台
手动发出的Message):
Message :
{
"body": "eyJ1c2VySWQiOiIxIiwgInJld2FyZEtleSI6Imludml0ZSIsICJ0aW1lIjoiMjAyMS0wNC0wNCAyMToxNToyMCJ9",
"messageProperties": {
"consumerQueue": "member.reward",
"consumerTag": "amq.ctag-JF9n7btz0tGCzE0pk9KO7w",
"contentLength": 0,
"deliveryTag": 1,
"finalRetryForMessageWithNoId": false,
"headers": {},
"lastInBatch": false,
"publishSequenceNumber": 0,
"receivedDeliveryMode": "PERSISTENT",
"receivedExchange": "mis.direct",
"receivedRoutingKey": "member.reward",
"redelivered": true
}
}
Message Body:
{
"userId": "1",
"rewardKey": "invite",
"time": "2021-04-04 21:15:20"
}
嗯,对比一下发现,确实有差别:"contentType": "text/plain"
。
传Object会是什么情况呢(通过 rabbitTemplate.convertAndSend(RabbitConfig.MIS_EXCHANGE, RabbitConfig.MEMBER_REWARD_ROUTING, jsonObject)
发出的Message):
Message :
{
"body": "rO0ABXNyAB9jb20uYWxpYmFiYS5mYXN0anNvbi5KU09OT2JqZWN0AAAAAAAAAAECAAFMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAADdAAJcmV3YXJkS2V5dAAIcmVnaXN0ZXJ0AAR0aW1ldAATMjAyMS0wNC0wNiAxMTo0NjozMXQABnVzZXJJZHQAATF4",
"messageProperties": {
"consumerQueue": "member.reward",
"consumerTag": "amq.ctag-7wnGu39A5POBeF753riU8Q",
"contentLength": 0,
"contentType": "application/x-java-serialized-object",
"deliveryTag": 2,
"finalRetryForMessageWithNoId": false,
"headers": {},
"lastInBatch": false,
"priority": 0,
"publishSequenceNumber": 0,
"receivedDeliveryMode": "PERSISTENT",
"receivedExchange": "mis.direct",
"receivedRoutingKey": "member.reward",
"redelivered": false
}
}
Message Body:
嗯,至此,规律已出现了。那该怎么解决呢?
解决办法1:对缝儿
让生产者发送消息的类型与消费者接收消息的类型一致。
生产者发送String类型("contentType": "text/plain"
)的消息:
rabbitTemplate.convertAndSend(RabbitConfig.MIS_EXCHANGE, RabbitConfig.MEMBER_REWARD_ROUTING, jsonObject.toString())
消费者接受String类型的消息:
@Component
@RabbitListener(queues = { RabbitConfig.MEMBER_REWARD_QUEUE })
public class Receiver {
@RabbitHandler
public void process(String msg) {
System.out.println("Receiver : " + msg);
JSONObject jsonObject = JSON.parseObject(msg);
...
}
}
生产者发送JSONObject类型("contentType": "application/x-java-serialized-object"
)的消息:
rabbitTemplate.convertAndSend(RabbitConfig.MIS_EXCHANGE, RabbitConfig.MEMBER_REWARD_ROUTING, jsonObject)
消费者接受String类型的消息:
@Component
@RabbitListener(queues = { RabbitConfig.MEMBER_REWARD_QUEUE })
public class Receiver {
@RabbitHandler
public void process(JSONObject jsonObject) {
System.out.println("Receiver : " + jsonObject.toJSONString());
...
}
}
依次类推。
解决办法2:消费者设置默认处理方法
不管生产者怎么生产消息。通过rabbitTemplate.convertAndSend
、amqp-client
、rabbitmq 管理后台
等发送均可。
消费者设置默认处理:
@Component
@RabbitListener(queues = { RabbitConfig.MEMBER_REWARD_QUEUE })
public class Receiver {
@RabbitHandler(isDefault = true)
public void process(Message message) {
// message.getBody() 为消息体
// 如果客户端发送的是String, new String(message.getBody()) 得到客户端发送的String
// 如果客户端发送的是Object, 此时接收到的是序列化后的Object,在这里需要反序列化得到Object
...
}
}
解决办法3:规避二义性
当把@RabbitListener
标注在类上面时,可以在多个方法上标注@RabbitHandler
。此时需要通过 isDefault
属性设置消息的默认处理方法。
当把@RabbitListener
标注在方法上面时,无法设置多个消息处理方法,就不存在二义性的问题。因此完美规避本错误。
参考这里。
解决办法4:生产者设置ContentType
参考这里。
- amqp-client发送消息时,设置ContentType:
@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<String, Object>())
.priority(0);
channel.basicPublish("testExchange", "many",builder.build(), message.getBytes());
}
- RabbitMQ管理后台删除无法处理的消息,再重新开程序,就没问题了。
另外一个类似的错误:Caused by: org.springframework.amqp.AmqpException: No method found for class java.lang.String
11:41:33.719 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#6-1] WARN o.s.a.r.l.ConditionalRejectingErrorHandler - [log,129] - Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener threw exception
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.wrapToListenerExecutionFailedExceptionIfNeeded(AbstractMessageListenerContainer.java:1722)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1612)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1527)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1515)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1506)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1450)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:976)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:922)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1297)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1203)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.amqp.AmqpException: No method found for class java.lang.String
at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getHandlerForPayload(DelegatingInvocableHandler.java:151)
at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getMethodFor(DelegatingInvocableHandler.java:271)
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.getMethodFor(HandlerAdapter.java:84)
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:148)
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:135)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1608)
... 10 common frames omitted
上一篇: 域控的建立
推荐阅读
-
Caused by: org.springframework.amqp.AmqpException: No method found for class [B
-
解决org.springframework.amqp.AmqpException: No method found for class [B 问题
-
org.springframework.amqp.AmqpException: No method found for class [B
-
解决rabbitmq无限循环异常问题亲测 Caused by: org.springframework.amqp.AmqpException: No method found for class [B
-
Page not found (404) Request Method: GET Request URL: http://127.0.0.1:8000/blog/about/ Raised by: b