Spring Boot-RabbitMQ-将消息内容类型从八位字节流更改为json

时间:2019-08-08 00:10:04

标签: spring spring-boot kotlin rabbitmq

从RabbitMQ中收到的Byte []消息转换为基于模型的对象时,我遇到了问题。

我正在使用Spring Boot。

在应用程序中,我实现了RabbitListenerConfigurer

@SpringBootApplication
class Application : RabbitListenerConfigurer {
...

override fun configureRabbitListeners(registrar: RabbitListenerEndpointRegistrar) {
        registrar.messageHandlerMethodFactory = messageHandlerMethodFactory()
    }

    @Bean
    fun messageHandlerMethodFactory(): MessageHandlerMethodFactory {
        val messageHandlerMethodFactory = DefaultMessageHandlerMethodFactory()
        messageHandlerMethodFactory.setMessageConverter(consumerJackson2MessageConverter())
        return messageHandlerMethodFactory
    }

    @Bean
    fun consumerJackson2MessageConverter(): MappingJackson2MessageConverter {
        return MappingJackson2MessageConverter()
    }

}

然后我有一个侦听器(println暂时供我检查),如:

@RabbitListener(queues = ["success.queue"])
    fun receivedSuccessMessage(data: MyModel) {
        println(data)
    }

模型本身看起来像(再次简化只是为了测试):

@JsonIgnoreProperties(ignoreUnknown = true)
data class MyModel(
        val input: Any,
        val metadata: Any
)

现在,只要该队列收到消息,我得到的错误就是:

Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot convert from [[B] to [com.models.MyModel] for GenericMessage [payload=byte[1429]

还要将我要接收的消息添加到该成功队列中,如下所示:

{"input":"somestuff", "metadata": "somestuff"}

我还刚刚注意到消息类型为content_type: application/octet-stream。这是我无法控制的,因为那正是我从将消息放入其中的服务所收到的:

enter image description here

这是为什么的任何想法-我假设我执行的RabbitListenerConfigurer会将所有消息从字节数组转换为我指定的任何模型。

任何帮助/想法都将不胜感激。

谢谢。

更新 好的,我已经开始工作了,但是我对某些事情感到困惑:

这是我添加的内容:

@Autowired
lateinit var connectionFactory : ConnectionFactory

@Bean
    fun rabbitListenerContainerFactory(): SimpleRabbitListenerContainerFactory {
        val factory = SimpleRabbitListenerContainerFactory()
        factory.setConnectionFactory(connectionFactory)
        factory.setAfterReceivePostProcessors(SomeBusiness())

        return factory
    }

然后是这样的实际转换:

class SomeBusiness : MessagePostProcessor {
    @Throws(AmqpException::class)
    override fun postProcessMessage(message: Message): Message {
        println("WE WENT IN NOW")
        println()
        if (message.messageProperties.contentType == "application/octet-stream") {
            message.messageProperties.contentType = "application/json"
        }
        return message
    }
}

但是我不明白的是,我已经有了messageHandlerMethodFactory函数,我假设它已经完成了监听消息的所有工作。现在,我有了rabbitListenerContainerFactory,可以担心是否存在任何冲突。还是完全有效,也就是说,我需要rabbitListenerContainerFactory来实现SimpleRabbitListenerContainerFactory,这使我可以访问方法setAfterReceivePostProcessors

再次,任何解释都将不胜感激。

谢谢

2 个答案:

答案 0 :(得分:0)

当您收到content_type: application/octet-stream时,此设置无法更改。 您可以使用Spring Interceptor或Servlet Filter将内容类型application/octet-stream转换为application/json

Example using HandlerInterceptor for Spring Boot希望对您有所帮助。谢谢

答案 1 :(得分:0)

请找到以下对我有用的资源

public void convertByteArrayToObject(Message<?> message) {

    Object request = message.getPayload();
    Object result = null;
    try {
        byte[] byteArray = (byte[]) request;
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);

        result = new ObjectInputStream(byteArrayInputStream).readObject();
    } catch (ClassNotFoundException | IOException e) {
        LOG.error(e.getMessage());
    }
    return result;
}