如何处理包更改的Java序列化对象?

Ale*_*dro 17 java versioning serialization

我有一个Java类存储在HttpSession对象中,该对象在集群环境中的服务器之间进行序列化和传输.出于此解释的目的,我们将此类称为"Person".

在改进代码的过程中,这个类从"com.acme.Person"转移到"com.acme.entity.Person".在内部,类保持完全相同(相同的字段,相同的方法,相同的一切).

问题是我们有两组服务器同时运行旧代码和新代码.具有旧代码的服务器具有序列化的HttpSession对象,并且当新代码反序列化它时,它会抛出ClassNotFoundException,因为它找不到对com.acme.Person的旧引用.此时,处理这个很容易,因为我们可以使用新包重新创建对象.然后问题变成新服务器中的HttpSession将使用对com.acme.entity.Person的新引用来序列化对象,并且当在运行旧代码的服务器中对其进行反序列化时,将抛出另一个异常.此时,我们再也无法处理此异常.

对于这类案件,最好的策略是什么?有没有办法告诉新服务器通过引用旧包序列化对象并将旧包的引用反序列化为新包?所有服务器运行新代码后,我们将如何过渡到使用新包并忘记旧包?

Ste*_*n C 16

我发现这篇博文声称有一个解决方案,但它并没有非常清楚地说明.

它实际上是说你创建了一个子类ObjectInputStream来覆盖readClassDescriptor方法来做这样的事情:

@Override
protected java.io.ObjectStreamClass readClassDescriptor() 
        throws IOException, ClassNotFoundException {
    ObjectStreamClass desc = super.readClassDescriptor();
    if (desc.getName().equals("oldpkg.Widget")) {
        return ObjectStreamClass.lookup(newpkg.Widget.class);
    }
    return desc;
};
Run Code Online (Sandbox Code Playgroud)

您还应该看看这个问题及其答案,其中包含与您的问题相同的一些问题.

我的建议是:支持旧版本软件读取新版本序列化数据的情况.

  • 这是鼓励(实际上强迫)人们升级到最新版本的代码库的好机会.一般来说,这种情况发生在所有人的利益之中,这种情况很快就会发生.

  • 如果由于其他原因迫使人们升级为时过早,那么(IMO)您应该认真考虑撤销对类/包名称的更改.等到你有一个明确的升级战略/计划,1)技术上合理,2)所有利益相关者都能接受.