我目前正在开发一个项目,该项目需要保留任何类型的对象(我们对其实现没有任何控制),以便之后可以恢复这些对象。

我们无法实现 ORM,因为我们无法在开发时限制库的用户。

我们的第一个选择是使用 Java 默认序列化来序列化它,但是当用户开始传递同一对象的不同版本(属性更改了类型、名称等)时,我们在恢复对象时遇到了很多麻烦。

我们尝试过使用 XMLEncoder 类(将对象转换为 XML),但我们发现缺乏功能(例如不支持枚举)。

最后,我们还尝试了 JAXB,但这迫使我们的用户注释他们的类。

有什么好的替代方案吗?

有帮助吗?

解决方案

你最容易做的事情仍然是使用序列化,IMO,但更多地考虑类的序列化形式(无论如何你应该做的)。例如:

  1. 明确定义SerialUID。
  2. 在适当的位置定义您自己的序列化表单。
  3. 序列化表单是API类的一部分,应仔细考虑其设计。

    我不会详细介绍很多细节,因为我所说的几乎所有内容都来自Effective Java。我会转而推荐你,特别是有关序列化的章节。它会警告您遇到的所有问题,并为问题提供正确的解决方案:

    http://www.amazon.com/Effective-Java-2nd-Joshua-布洛赫/ DP / 0321356683


    话虽如此,如果您仍在考虑非序列化方法,请参阅以下内容:

    XML编组

    许多人已经指出这是一个选项,但我认为你仍会遇到向后兼容性相同的问题。但是,使用XML编组,您可能会立即捕获这些内容,因为某些框架可能会在初始化期间为您进行一些检查。

    转换为/来自YAML

    这是我一直在想的一个想法,但我真的很喜欢YAML格式(至少作为自定义toString()格式)。但实际上,唯一不同的是你要编组YAML而不是XML。唯一的好处是YAML比XML更具人性化。同样的限制也适用。

其他提示

现在是 2011 年,在商业级 REST Web 服务项目中,我们使用以下序列化器为客户提供各种媒体类型:

  • 流媒体 (适用于 XML,但不适用于 JSON)
  • 杰克逊 (对于 JSON)
  • 克里奥 (一种快速、紧凑的二进制序列化格式)
  • 微笑 (Jackson 1.6 及更高版本附带的二进制格式)。
  • Java 对象序列化。

我们最近尝试了其他序列化器:

  • 简单XML 看起来很可靠,运行速度是 XStream 的 2 倍,但对于我们的情况来说需要太多配置。
  • YamlBeans 有一些错误。
  • 蛇YAML 有一个与日期有关的小错误。

Jackson JSON、Kryo 和 Jackson Smile 都比传统的 Java 对象序列化快得多,大约快 3 倍到 4.5 倍。XStream 速度较慢。但目前这些都是可靠的选择。我们将继续监视其他三个人。

http://x-stream.github.io/ 很不错,请带一个看它!非常方便

  

我们没有任何控制的实施

解决方案不要这样做。如果您无法控制类型的实现,则不应将其序列化。故事结局。 Java序列化提供了serialVersionUID,专门用于管理不同版本的类型之间的序列化不兼容性。如果您不控制实现,则在开发人员更改类时无法确定ID是否正确更改。

举一个'点'的简单例子。它可以用笛卡尔坐标系或极坐标系表示。构建一个可以动态应对这些修正的系统将是成本过高的 - 它必须是设计序列化的类的开发人员。

简而言之,这是你的设计错了 - 而不是技术。

Google提出了二进制协议 - http://code.google.com/apis/ protocolbuffers / 更快,与XML相比具有更小的有效负载 - 其他人建议将其作为备用。

协议缓冲区的一个优点是它可以与C,C ++,python和java交换信息。

尝试使用 Gson 序列化为json。

另一种非常快速的JDK序列化替代品: http://ruedigermoeller.github.io/fast-serialization/

如果序列化速度对您很重要,那么这里有一个 JVM 序列化器的综合基准测试:

就个人而言,我使用成名,因为它具有与Smalltalk(VW和吱吱声)和Python。 (免责声明,我是Fame项目的主要贡献者。)

可能会 Castor

Betwixt 是一个很好的用于序列化对象的库 - 但它不会是一个自动类型事情如果您必须序列化的对象数量相对固定,这对您来说可能是一个不错的选择,但如果您的“客户”将一直向您投掷新课程,则可能需要付出更多努力(对于所有特殊情况,绝对比XMLEncoder更容易。

另一种方法是要求您的客户为他们抛出的任何对象提供相应的.betwixt文件(这有效地将责任转移给他们)。

长短 - 序列化是 hard - 没有完全脑死亡的方法。 Java序列化与我所见过的脑死亡解决方案一样接近,但正如您所发现的,不正确使用版本的uid值可能会破坏它。 Java序列化还需要使用标记'Serializable'接口,所以如果你无法控制你的源代码,那你就有点不幸了。

如果要求真的像你描述的那样艰巨,你可能不得不在对象/方面/其他方面采用某种BCE(字节代码修改)。这远远超出了一个小型开发项目的领域,进入了Hibernate,Casper或ORM领域....

另一个想法:使用缓存。缓存为应用程序提供了更好的控制、可扩展性和鲁棒性。虽然仍然需要序列化,但在缓存服务框架内管理变得更加容易。缓存可以持久保存在内存、磁盘、数据库或阵列中,或者所有选项中,其中一个是溢出、备用、另一个是故障转移。Commons JCS 和 Ehcache 是两个 java 实现,后者是一个企业解决方案,可释放高达 32 GB 的存储空间(免责声明:我不为 ehcache 工作;-))。

SBE是一个用于快速,基于字节缓冲的序列化库并且能够进行版本控制的已建立的库。但是,由于需要在其上编写长度包装类,因此使用起来有点困难。

鉴于它的缺点,我最近创建了一个仅受Java限制的序列化库,其灵感来自SBE和FIX协议(用于交换交易/报价消息的通用金融市场协议),试图在克服它们的同时保持两者的优势弱点。你可以看看 https://github.com/iceberglet/anymsg

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top