AMQP(RabbitMQ)无法反序列化对象ClassNotFoundException

时间:2016-07-11 06:54:17

标签: java serialization rabbitmq classnotfoundexception amqp

我想在java SpringBoot中实现一个RabbitMq(AMQP)消息,但是当我收到消息时它说无法反序列化,因为即使我没有找到我应该收到的对象的类将该类放在类路径中。

RabbitMqListener.java:

\Page\dashboardBundle\Entity\Cars as Cars;

RabbitConfiguration.java:

@EnableRabbit
@Component
public class RabbitMqListener {
    Logger logger = Logger.getLogger(RabbitMqListener.class);

    @RabbitListener(queues = "queue2")
    public void processQueue1(Product message) {

        logger.info("Received from queue 2: " + message);
    }

}

SampleController.java:

@Configuration
public class RabbitConfiguration {
    Logger logger = Logger.getLogger(RabbitConfiguration.class);
    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory =
                new CachingConnectionFactory("localhost");
        return connectionFactory;
    }

    @Bean
    public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(connectionFactory());
    }

    @Bean
    public MessageConverter jsonMessageConverter(){
        return new JsonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setMessageConverter(jsonMessageConverter());
        return template;
    }


    @Bean
    public Queue myQueue1() {

        return new Queue("queue1");
    }

    @Bean
    public Queue myQueue2() {

        return new Queue("queue2");
    }

}

Product.java:

@Controller
public class SampleController {
    Logger logger = Logger.getLogger(SampleController.class);

    @Autowired
    AmqpTemplate template;

    @RequestMapping("/emit")
    @ResponseBody
    String queue1() {
        logger.info("Emit to queue1");
        template.convertAndSend("queue1","Message to queue 1");
        return "Emit to queue 1";
    }
}

和堆栈跟踪:

public class Product implements Serializable{

    private Long id;

    private String name;

    private int stock;

    private int price;



    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getStock() {
        return stock;
    }

    public void setStock(int stock) {
        this.stock = stock;
    }

    public Product() {
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", stock=" + stock +
                ", price=" + price +
                '}';
    }
}

3 个答案:

答案 0 :(得分:2)

在代码片段中,您已经注册了jsonMessageConverter,同时您正在使Person.java可序列化。您应该使用序列化或json方法。而且问题在于Person.java的包结构。我遇到了同样的问题,通过为生产者和消费者中传输的对象采用相同的包结构来解决它。这背后的原因是,在序列化时,java会考虑类名,包结构和其他信息,因此在消费者方面我们需要具有相同的包结构。我在使用jsonMessageConverter时遇到了同样的问题。因此,从我的观点来看,这个问题的解决方案是将消息对象打包到jar中,并将该jar作为依赖项添加到生产者和消费者项目中。

答案 1 :(得分:1)

使用rabbitmq时,应将您的班级放在同一个名称包中, 例如:com.xxx.entity.Order。如果class位于com.xxx.consumer.entity.Order``com.xxx.producer.entity.Order之类的其他包中,则会抛出错误。

答案 2 :(得分:0)

对于那些从 IntelliJ 来到这里并且在使用 消息队列 时仍未解决此类或类似 ClassNotFoundException 问题的人;很可能您正在处理两个或更多不同的项目,并且您甚至可能在同一根目录下拥有这些项目,但您仍然会遇到此异常,因为这两个或更多项目未设置为IntelliJ 中的单个项目。此外,要序列化和/或反序列化对象 RabbitMQ 需要相同的类,但您可能在不同的项目中有两个相似的类。

要解决这个问题,你可以按照这个技巧:

  1. 在包含“不相交”项目的根文件夹中创建一个新的空项目。
  2. IntelliJ 会提示你将这些项目作为模块导入到这个空项目中;选择 pom.xmlbuild.gradle 文件以导入它们。
  3. 按“确定”,项目将加载到您之前为空的项目下。
  4. 现在,剩下的就是对这些模块进行分组。您可以通过以下方式执行此操作 - IntelliJ's Guide for Grouping Modules
  5. 在对模块进行分组后,您可以(从不同模块中删除一个或多个类 - 只保留该类的一个实现)通过向模块添加 Maven 或 Gradle 依赖项,从所需模块导入所需的类.

如果您使用的是 Maven,那么您的 pom.xml 文件中的依赖项应如下所示:

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>commons</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>compile</scope>
</dependency>