【问题标题】:Serialization and Deserialization through message queue通过消息队列进行序列化和反序列化
【发布时间】:2017-01-16 22:07:39
【问题描述】:

我有一个Employee 类如下:

package com.mypackage.rabbitmq.model
import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement
public class Employee implements Serializable{

    /**
    * 
    */
    private static final long serialVersionUID = -2736911235490297622L;
    private int EmpNo;
    private String FirstName;
    private String LastName;
    private int age;
    private String gender;
    private String skill;
    private long phone;
    private String email;
    private double salary;
    //getters and setters

我在rabbit MQ中发布了员工名单如下:

package com.mypackage.rabbitmq.client.publisher;

//imports

public class Publisher {

    public static void main(String[] args) throws IOException {
        ConnectionFactory factory = new ConnectionFactory();

        Connection con = factory.newConnection("localhost");
        Channel channel = con.createChannel();

        Gson gson  = new GsonBuilder().create();
        Employee employee = null;

        List<Employee> empList = new ArrayList<>();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        String queueName = "TestQueue";
        for(int i=1; i<=10; i++){
            employee = newEmp(i);

            String message =gson.toJson(employee);
            System.out.println("queueName: "+queueName);
            empList.add(employee);

        }
        oos.writeObject(empList);
        channel.basicPublish(1, "", queueName, null, bos.toByteArray());
        System.out.println("[X], sent '"+empList+"'");

        channel.close(0, queueName);
        con.close(0, queueName);
    }

    public static Employee newEmp(int i){

        //logic here
    }
}

从一个单独的 Spring Boot 应用程序中,我尝试使用员工列表。在消费者应用程序中,我有相同的员工类结构。但是包装不同。

package org.springboot.consumer.model;

import java.io.Serializable;

public class Employee implements Serializable{
    //fields and getters-setters here
}

简单的消费者代码如下:

public class SDPRabbitMQConsumer implements MessageListener {

    @Override
    public void onMessage(Message message) {
        Gson gson  = new GsonBuilder().create();
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            os.write(message.getBody(), 0, message.getBody().length);
            ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
            ObjectInputStream objInputStream = new ObjectInputStream(is);
            System.out.println("objInputStream.readObject().toString()"+objInputStream.readObject().toString());
            Employee[] employeeArray = gson.fromJson(objInputStream.readObject().toString(), Employee[].class);
            List<Employee> employeeList = new ArrayList<Employee>(Arrays.asList(employeeArray));
            for(Employee employee: employeeList){
                System.out.println(employee);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

但我得到以下异常:

java.lang.ClassNotFoundException: com.mypackage.rabbitmq.model.Employee

这似乎是一个序列化和反序列化问题。

我的问题是:

  1. 如果我发布 Employee 而不是 List,我什至不需要序列化类。那为什么我需要在 List 的情况下进行序列化呢?
  2. 为什么会出现这个异常?我们是否需要在两端为序列化类维护相同的包结构?
  3. 在消费者端我们需要有serialVersionUID吗?如果是,是否应该与发布方的一致?

提前致谢。

【问题讨论】:

    标签: java serialization spring-boot rabbitmq deserialization


    【解决方案1】:

    1) 虽然 java.util.List 不可序列化,但所有标准实现都是可序列化的,因此您应该能够序列化/反序列化例如 ArrayList。

    2) 是的,你需要同一个包中的同一个类,而且..

    3) 两端的类必须具有相同的serialVersionUID

    【讨论】:

    • 谢谢。不过我有一个疑问。正如我所提到的,如果我发布员工对象的字节数组而不序列化 Employee 类,而不是 List,我可以在消费者端构造它。这怎么可能?
    • “没有序列化 Employee 类的员工对象的字节数组”没有意义,一个字节数组只能包含字节。您正在沿通道发送字节,通道总是以您呈现它的方式获取字节,您在顶部添加序列化层。
    • 好吧,之前我没有序列化 Employee 类并在频道中发布如下String message =gson.toJson(employee); channel.basicPublish(1, "", queueName, null, message.getBytes()); 在消费者方面我能够得到对象如下String msg = new String(message.getBody()); Employee employee = gson.fromJson(msg, Employee.class);
    • 是的,那样你不使用 Java 序列化,而是使用 Json 序列化。归根结底,队列不知道您要发送什么,只是从一端获取字节并将它们放在另一端取决于您希望如何对该信息进行编码以使其有意义
    • 哦,好吧。我得到了它。谢谢@Ulises
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-08
    • 2018-11-15
    • 2019-08-15
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多