GWT-RPC服务应该使用java.io.Serializable作为参数类型吗?

GWT-RPC服务应该使用java.io.Serializable作为参数类型吗?,gwt,serialization,gwt-rpc,Gwt,Serialization,Gwt Rpc,我在GWT中定义一个简单的“键值存储”服务;我将编写服务器,但让其他人编写客户端,所以应该尽可能简单。我希望客户端能够使用字符串键,但不能使用任何可序列化类型的值。所以我定义了接口: public void put(String key, java.io.Serializable value); public java.io.Serializable get(String key); interface Store<T extends Serializable & IsSeria

我在GWT中定义一个简单的“键值存储”服务;我将编写服务器,但让其他人编写客户端,所以应该尽可能简单。我希望客户端能够使用字符串键,但不能使用任何可序列化类型的值。所以我定义了接口:

public void put(String key, java.io.Serializable value);
public java.io.Serializable get(String key);
interface Store<T extends Serializable & IsSerializable> {
void put(String key, String value);
void put(String key, Number value);
void put(String key, T value);

Integer getInt(String key);
Double getDouble(String key);
BigDecimal getBigDecimal(String key);
String getString(String key);
IsSerializable get(String key);
}
这很好,但有一个问题:Eclipse对这两种方法都给出了以下警告:

正在检查符合序列化条件的对象的所有子类型

谷歌搜索该警告,似乎GWT将为程序中的每一种类型生成一段代码。因此,这可能相当昂贵。我很困惑,因为我认为Serializable接口中的所有类型都已经有了序列化代码,它可以调用它(但可能序列化代码只在这种情况下生成)

所以我有几个问题:

  • 这会使客户端代码更大和/或更慢吗?这个问题有多严重
  • 我看到GWT提供了一个独立的接口
    IsSerializable
    。我可以用它来代替吗?我试过了,但是我注意到像String和Integer这样的基本类并没有实现这个接口
  • 如果我让RPC层改为使用
    byte[]
    ,但为我的客户机提供一个包装器方法,将
    java.io.Serializable
    序列化为
    byte[]
    ,这会解决问题吗,还是会导致与我开始时相同的代码膨胀问题
  • 有没有更好的方法来实现一个键值存储,它允许任意类型的值,而不需要为客户端做太多的工作
  • 如果我坚持使用Serializable,有没有办法抑制该警告
我看到GWT提供了一个可串行化的单独接口。我可以用它来代替吗?我试过了,但是我注意到像String和Integer这样的基本类并没有实现这个接口

对。IsSerializable优于java.io.Serializable。以下列出了原因:

  • GWT序列化的语义远没有标准Java序列化复杂,因此使用Java.io.Serializable作为标记接口意味着GWT的序列化系统能够实现比实际更多的功能
  • 相反,GWT的序列化机制比标准Java的简单,因此使用Java.io.Serializable意味着用户比实际更需要担心(比如序列化版本ID)
  • GWT只实现完整Java JRE类的一个子集,在Java.io中没有具体实现任何东西。将java.io.Serializable用作GWT RPC序列化标记接口会稀释java.io在GWT应用程序中不可用的消息
>

如果我让RPC层改用byte[],但为我的客户机提供一个包装器方法,将java.io.Serializable序列化为byte[],这会解决问题吗,还是会导致与我开始时相同的代码膨胀问题

坏主意。在这种情况下,从对象到字节[]的序列化将在客户端的JavaScript中进行。是的,序列化在客户端是可能的,但是使用GWT协议;这不是Java序列化。浏览器做不到这一点

有没有更好的方法来实现一个键值存储,它允许任意类型的值,而不需要为客户端做太多的工作

不幸的是,我认为您不可能对所有类都使用一个真正的方法。我建议您尝试以下界面:

public void put(String key, java.io.Serializable value);
public java.io.Serializable get(String key);
interface Store<T extends Serializable & IsSerializable> {
void put(String key, String value);
void put(String key, Number value);
void put(String key, T value);

Integer getInt(String key);
Double getDouble(String key);
BigDecimal getBigDecimal(String key);
String getString(String key);
IsSerializable get(String key);
}
接口存储{
作废放置(字符串键、字符串值);
作废放置(字符串键、数字值);
作废put(字符串键,T值);
整数getInt(字符串键);
Double-getDouble(字符串键);
BigDecimal getBigDecimal(字符串键);
字符串getString(字符串键);
IsSerializable get(字符串键);
}
泛型确保对象同时具有两个接口,这样您就可以同时使用GWT协议(从客户端到服务器)和Java序列化(从服务器到数据存储)进行序列化

编辑回答评论:

对于最后一种解决方案,泛型不是意味着存储只能存储单一类型的对象,并且如果客户机想要存储不同的对象,他必须创建一个新的存储吗

是的,客户端必须为每种类型创建一个新的存储。如果这真的让您感到困扰,那么解决方案是创建一个新的接口MySerializable,它扩展了IsSerializable和java.io.Serializable;但是,每个对象都必须实现它,这会创建对项目的依赖

另外,它不要求对象是可序列化和可序列化的吗

是的,这是一个好处。否则,服务器端可能有一个不可java.io.Serializable的对象;若你们试图将它提供给方法,一个异常会在你们面前爆发

最后,关于我的第一个问题:仅仅使用io.Serializable实际上会影响代码大小/性能吗


从实际使用情况来看,我不能这么说,但我不这么认为:两者都只是标记接口。GWT系列化对于这两个版本都是一样的。

谢谢您的建议。哎哟,看来没有简单的出路。对于最后一种解决方案,泛型不是意味着存储只能存储单一类型的对象,并且如果客户机想要存储不同的对象,他必须创建一个新的存储吗?另外,它不要求对象是可序列化和可序列化的吗?最后,关于我的第一个问题:仅仅使用io.Serializable是否真的会影响代码大小/性能?谢谢你提供的额外信息。我想我要冒这个险,尽管有警告,还是使用java.io.Serializable。但是谢谢你清楚地解释了这个问题的各个方面。注意:至于压制这个警告,目前似乎没有办法做到这一点。有一个国际空间站