Java RabbitMQ的Spring SimpleMessageListenerContainer正在中止无效消息
我正在使用springs SimpleMessageListenerContainer来使用RabbitMQ队列中的消息。一切正常,但当向队列发送无效消息(例如无效json)时,侦听器只是中止,关闭工作进程,不接受任何进一步的消息 是否可以将其配置为丢弃已断开的消息并继续侦听其他消息 我正在使用sprint-rabbit-1.6.1.RELEASE.jar 我的配置如下所示:Java RabbitMQ的Spring SimpleMessageListenerContainer正在中止无效消息,java,spring,rabbitmq,spring-rabbit,Java,Spring,Rabbitmq,Spring Rabbit,我正在使用springs SimpleMessageListenerContainer来使用RabbitMQ队列中的消息。一切正常,但当向队列发送无效消息(例如无效json)时,侦听器只是中止,关闭工作进程,不接受任何进一步的消息 是否可以将其配置为丢弃已断开的消息并继续侦听其他消息 我正在使用sprint-rabbit-1.6.1.RELEASE.jar 我的配置如下所示: @Bean public SimpleMessageListenerContainer container(Connec
@Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter,
MessageConverter messageConverter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("my.queue");
container.setMessageListener(listenerAdapter);
container.setMessageConverter(messageConverter);
return container;
}
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
MessageListenerAdapter listenerAdapter(Worker worker) {
MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(worker, "processMessage");
messageListenerAdapter.setMessageConverter(new Jackson2JsonMessageConverter());
return messageListenerAdapter;
}
my listener方法的声明:
public void processMessage(Map<String, String> message) {
SimpleMessageListenerContainer中的致命异常在此处引发:
catch (ListenerExecutionFailedException ex) {
// Continue to process, otherwise re-throw
if (ex.getCause() instanceof NoSuchMethodException) {
throw new FatalListenerExecutionException("Invalid listener", ex);
}
}
因此,如果容器配置了一个不存在的方法,那么它似乎应该关闭。但是,在消息中断的情况下,它试图使用错误的参数类型调用该方法,这也会导致NoSuchMethodException。这意味着任何制作人都可以用一条坏消息杀死我的消费者
谢谢你的建议 有趣;我能够复制你的问题;事实证明,如果消息不包含
\uuuuu TypeID\uuuu
头(转换提示),它只会以字符串形式返回“坏”json
我可以通过向转换器中注入自定义类映射器来解决这个问题
您还可以让发送系统设置类型标头
然后,消息被拒绝,因为我们得到了MessageConversionException
package com.example;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.ClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class So39264965Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(So39264965Application.class, args);
RabbitTemplate template = context.getBean(RabbitTemplate.class);
template.convertAndSend("my.queue", new Foo());
context.getBean(Worker.class).latch.await(60, TimeUnit.SECONDS);
// bad json
template.setMessageConverter(new SimpleMessageConverter());
template.convertAndSend("", "my.queue", "\"routeId\":\"7\"}", m -> {
m.getMessageProperties().setContentType("application/json");
return m;
});
Thread.sleep(60000);
context.close();
}
@Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter, MessageConverter messageConverter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("my.queue");
container.setMessageListener(listenerAdapter);
container.setMessageConverter(messageConverter);
return container;
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter());
return rabbitTemplate;
}
@Bean
public Queue queue() {
return new Queue("my.queue");
}
@Bean
public MessageConverter messageConverter() {
Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
jackson2JsonMessageConverter.setClassMapper(new ClassMapper() {
@Override
public Class<?> toClass(MessageProperties properties) {
return Foo.class;
}
@Override
public void fromClass(Class<?> clazz, MessageProperties properties) {
}
});
return jackson2JsonMessageConverter;
}
@Bean
MessageListenerAdapter listenerAdapter(Worker worker) {
MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(worker, "processMessage");
messageListenerAdapter.setMessageConverter(messageConverter());
return messageListenerAdapter;
}
@Bean
public Worker worker() {
return new Worker();
}
public static class Worker {
private final CountDownLatch latch = new CountDownLatch(1);
public void processMessage(Foo foo) {
System.out.println(foo);
this.latch.countDown();
}
}
public static class Foo {
private String bar = "bar";
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
@Override
public String toString() {
return "Foo [bar=" + this.bar + "]";
}
}
}
package.com.example;
导入java.util.concurrent.CountDownLatch;
导入java.util.concurrent.TimeUnit;
导入org.springframework.amqp.core.MessageProperties;
导入org.springframework.amqp.core.Queue;
导入org.springframework.amqp.rabbit.connection.ConnectionFactory;
导入org.springframework.amqp.rabbit.core.RabbitTemplate;
导入org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
导入org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
导入org.springframework.amqp.support.converter.ClassMapper;
导入org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
导入org.springframework.amqp.support.converter.MessageConverter;
导入org.springframework.amqp.support.converter.SimpleMessageConverter;
导入org.springframework.boot.SpringApplication;
导入org.springframework.boot.autoconfigure.springboot应用程序;
导入org.springframework.context.ConfigurableApplicationContext;
导入org.springframework.context.annotation.Bean;
@SpringBoot应用程序
公共类SO39264965应用程序{
公共静态void main(字符串[]args)引发异常{
ConfigurableApplicationContext上下文=SpringApplication.run(So39264965Application.class,args);
RabbitTemplate=context.getBean(RabbitTemplate.class);
convertAndSend(“my.queue”,new Foo());
getBean(Worker.class).lack.await(60,TimeUnit.SECONDS);
//错误的json
setMessageConverter(新的SimpleMessageConverter());
template.convertAndSend(“,”my.queue“,“\”routeId\“:\”7\“}”,m->{
m、 getMessageProperties().setContentType(“应用程序/json”);
返回m;
});
睡眠(60000);
context.close();
}
@豆子
公共SimpleMessageListenerContainer容器(ConnectionFactory ConnectionFactory,
MessageListenerAdapter listenerAdapter,MessageConverter MessageConverter){
SimpleMessageListenerContainer容器=新SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(“my.queue”);
setMessageListener(listenerAdapter);
container.setMessageConverter(messageConverter);
返回容器;
}
@豆子
公共RabbitTemplate RabbitTemplate(连接工厂连接工厂){
RabbitTemplate RabbitTemplate=新的RabbitTemplate(连接工厂);
setMessageConverter(messageConverter());
返回兔模板;
}
@豆子
公共队列(){
返回新队列(“my.Queue”);
}
@豆子
public MessageConverter MessageConverter(){
Jackson2JsonMessageConverter Jackson2JsonMessageConverter=新Jackson2JsonMessageConverter();
jackson2JsonMessageConverter.setClassMapper(新类映射器(){
@凌驾
公共类到类(MessageProperties属性){
返回Foo.class;
}
@凌驾
来自类的公共void(类clazz、MessageProperties){
}
});
返回jackson2JsonMessageConverter;
}
@豆子
MessageListenerAdapter listenerAdapter(工作者){
MessageListenerAdapter MessageListenerAdapter=newmessagelisteneradapter(worker,“processMessage”);
messageListenerAdapter.setMessageConverter(messageConverter());
返回消息listeneradapter;
}
@豆子
公职人员(){
返回新工人();
}
公共静态类工作者{
专用最终倒计时闩锁=新倒计时闩锁(1);
公共无效处理消息(Foo-Foo){
系统输出打印项次(foo);
这个.latch.countDown();
}
}
公共静态类Foo{
私有字符串bar=“bar”;
公共字符串getBar(){
返回此.bar;
}
公共空心立根杆(弦杆){
这个.bar=bar;
}
@凌驾
公共字符串toString(){
返回“Foo[bar=“+this.bar+”]”;
}
}
}
我不确定您所说的是什么意思,但如果消息中断,它试图使用错误的参数类型调用该方法,这也会导致NoSuchMethodException。
。您需要显示完整的堆栈跟踪,而不是已编辑的堆栈跟踪,您使用的是什么版本?通常,错误的JSON会导致MessageConversionExceptio
package com.example;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.ClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class So39264965Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(So39264965Application.class, args);
RabbitTemplate template = context.getBean(RabbitTemplate.class);
template.convertAndSend("my.queue", new Foo());
context.getBean(Worker.class).latch.await(60, TimeUnit.SECONDS);
// bad json
template.setMessageConverter(new SimpleMessageConverter());
template.convertAndSend("", "my.queue", "\"routeId\":\"7\"}", m -> {
m.getMessageProperties().setContentType("application/json");
return m;
});
Thread.sleep(60000);
context.close();
}
@Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter, MessageConverter messageConverter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames("my.queue");
container.setMessageListener(listenerAdapter);
container.setMessageConverter(messageConverter);
return container;
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter());
return rabbitTemplate;
}
@Bean
public Queue queue() {
return new Queue("my.queue");
}
@Bean
public MessageConverter messageConverter() {
Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
jackson2JsonMessageConverter.setClassMapper(new ClassMapper() {
@Override
public Class<?> toClass(MessageProperties properties) {
return Foo.class;
}
@Override
public void fromClass(Class<?> clazz, MessageProperties properties) {
}
});
return jackson2JsonMessageConverter;
}
@Bean
MessageListenerAdapter listenerAdapter(Worker worker) {
MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(worker, "processMessage");
messageListenerAdapter.setMessageConverter(messageConverter());
return messageListenerAdapter;
}
@Bean
public Worker worker() {
return new Worker();
}
public static class Worker {
private final CountDownLatch latch = new CountDownLatch(1);
public void processMessage(Foo foo) {
System.out.println(foo);
this.latch.countDown();
}
}
public static class Foo {
private String bar = "bar";
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
@Override
public String toString() {
return "Foo [bar=" + this.bar + "]";
}
}
}