8

我正在通过 Web 服务传递一些对象,其中一些包含 java.sql.Date。因为 Date 没有空的构造函数,所以它不想被序列化。

问题的第一部分很简单:在客户和服务之间传递日期的最佳方式是什么?

第二部分有点棘手:一旦我决定如何传递日期,我显然可以声明日期瞬态并制作一些包装类以将日期作为 String 或其他方式传递,但是如何将相同的解决方案尽可能透明地应用于包括 Date 的几个类?

(我有一种预感,DynamicProxy thingy 可能是一个解决方案,但阅读 Sun 网站上的文档并不是很有帮助,所以如果它确实是朝那个方向发展的,将不胜感激)

编辑:我问错了问题,对不起(我和同事之间有些误解,实际上是什么问题)。由于反序列化而出现问题。因此,一旦我有 xml 格式的日期,它就会尝试将自己反序列化为 GregorianCalendar。问题的其他部分仍然存在:接收某些东西(长时间戳或 GregorianCalendar)并将其转换为 sql 日期的最佳方式是什么,而不为 10 个不同的类制作 10 个不同的包装器。我正在使用 NetBeans 进行代码和 wsdl 生成。

4

12 回答 12

9

乔达时间

Date 类有一个笨拙的 API。更好的实现是Joda-Time

ISO 8601

Joda-Time 还允许您将日期转换为ISO 8601标准格式 (yyyy-mm-ddTHH:MM:SS.SSS)。在将日期从服务器移动到客户端时使用此标准具有以可读格式包含完整日期的优势。例如,当您使用JAXB时,日期的 XML 表示也是这个 ISO 标准。(参见 XMLGregorianCalendar 类)

于 2008-09-22T12:52:54.423 回答
6

按照之前的建议序列化 Date.getTime() 返回的 long 将起作用。但是,您应该注意,如果您的服务器与客户端位于另一个时区,那么您将在另一端重建的日期将有所不同。如果您想重建完全相同的日期对象,您还需要发送您的时区 (TimeZone.getID()) 并使用它来重建另一边的日期。

于 2008-09-22T12:45:34.193 回答
3

为了回答您问题的第一部分,我建议使用 iso 8601 格式的字符串(这是编码日期的标准)。

对于第二部分,我不确定您为什么需要代理类?或者为什么你必须扩展日期类来支持这一点。例如。您的 Web 服务不会知道某个字段是日期并进行从日期到字符串的转换并返回自身吗?我需要更多信息。

于 2008-09-22T13:08:19.240 回答
2

java.sql.Date 扩展 java.util.Date

只需使用 getTime() 从中获取长值。这可以被序列化,并在另一端从它构造一个新的 java.sql.Date(long) 或 new java.util.Date(long)。

于 2008-09-22T12:34:35.123 回答
1

我研究了 java.sql.Date 的实现,我认为 java.sql.Date 是可序列化的,是 java.util.Date 的扩展。

于 2008-09-22T12:47:06.263 回答
1

java.sql.Date 最近对我有一个警告,它不只存储日期部分的时间部分(小时、分钟、秒等)。如果你想要完整的时间戳,你必须使用 java.util.Date 或 java.sql.Timestamp

于 2008-09-22T18:26:50.720 回答
1
于 2015-01-20T03:52:58.657 回答
0

您可以使用编码器和解码器来序列化和反序列化您的对象。

这是一个序列化 SWT Rectangle 类的示例:

XMLEncoder encoder = new XMLEncoder(new FileOutputStream(file));
encoder.setPersistenceDelegate(
    Rectangle.class, 
    new DefaultPersistenceDelegate(new String[]{"x", "y", "width", "height"}));
encoder.writeObject(groups);
encoder.close();
于 2008-09-22T12:45:53.693 回答
0

java.sql.Date 已经实现了 Serializable 所以不需要实现它:-)

就您的主要问题而言,我非常喜欢 JAXB,因为我几乎可以将任何 XML 转换为对象,因此可能值得您花时间研究它。

于 2008-09-22T13:43:10.153 回答
0

首先,如果您使用 Web 服务,这意味着您正在序列化为 XML,而不是常规的 Java 序列化(而是一些其他用于编组和解组的库)。所以这个问题缺乏一些信息。

其次,如果您可以控制 InputStream 和 OutputStream,请尝试扩展 ObjectOutputStream 和 ObjectInputStream 并覆盖replaceObject()resolveObject(),然后您可以为 java.sql.Date 实现序列化。

于 2008-09-22T12:36:26.057 回答
0

您不需要默认构造函数(空)来序列化/反序列化日期(java.sql.Date 或 java.util.Date)。在反序列化期间,不调用构造函数,而是将对象的属性直接设置为序列化数据中的值,并且您可以按原样使用对象,因为它已反序列化。

于 2008-09-22T12:43:40.843 回答
0

嗯......想不出任何理由为什么任何序列化的对象实例(通过默认的java机制序列化)应该将自己反序列化为另一个类的实例,因为类信息应该是序列化数据的固有部分。

因此,这要么是您的(反)序列化框架的问题,要么是框架在“发送端”(日历、java.util.Date 等)上接受任何“类似日期”的对象 - 因此 java.sql.Date 也是它扩展了 java.util.Date),将其“序列化”为某种常见日期格式的字符串(因此类型信息丢失),并将其“反序列化”回接收端的 Calendar 对象。

所以我认为获取 java.sql.Date 的最简单方法是执行

java.sql.Date date = new java.sql.Date(calendar.getTimeInMillis);

你需要一个 java.sql.Date 但从“反序列化”中获取 GregorianCalendar 。

于 2008-09-22T14:22:24.350 回答