修改:发送消息和订阅消息取消使用amqp提供的消息序列化和反序列化功能,使用String类型,发送前手动将消息转换成json字符串它,消费消息时手动json反序列化。背景:如果使用自动序列化反序列化功能,即为Rabbitmq配置Jackson2JsonMessageConverter消息转换器,当我们修改消息体的java类型名或包名时,消费历史消息会抛出ClassNotFoundException异常。1.线上不做兼容,但需要:保证不会有新的消息进入队列;确保队列中的消息已被消费。2、粗暴的方式,直接清空队列,丢弃历史消息;3.为了兼容性,为旧消息创建一个匹配类名的消息Body类型,并添加@RabbitHandler方法来处理旧消息。这是因为Rabbitmq为了实现一个队列,支持多方法消费(即@RabbitHandler注解的方法)。每个方法使用不同的Java类型的消息体。消费消息时,需要先反序列化消息体。根据消息体的类型,匹配一个消费方法来消费消息,如DelegatingInvocableHandler#invoke方法源码所示。//org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler#invokepublicInvocationResultinvoke(Message>message,Object...providedArgs)throwsException{//获取消息体类型ClasspayloadClass=message.getPayload().getClass();//匹配方法InvocableHandlerMethodhandler=getHandlerForPayload(payloadClass);//调用方法消费Objectresult=handler.invoke(message,providedArgs);//....}因为在Parse之前需要匹配消息消费方法消息体,即必须先知道消息体的Java类型才能实现json反序列化,这就需要消息生产者在发送消息时在消息头中添加一个参数来指明消息体的Java类型,如下图所示。在消息消费阶段,Jackson2JsonMessageConverter还需要先根据消息头的TypeId获取JavaType,然后进行反序列化操作。当类名被修改,或者生产者和消费者定义的类名不同时,都会导致反序列化失败。不建议使用自动序列化和反序列化功能,除非你保证消息体的类名不会改变,并且生产者和消费者定义的完整类名相同。本文转载自微信公众号“爪哇艺术”,作者无九爷。转载本文请联系爪哇艺术公众号。
