我想使用相同的代码在客户端和服务器端对对象进行排序和操作。
但我面临一个问题,因为在客户端我们需要一个代表服务器类的代理接口。
有没有办法在两者中使用相同的接口?我知道 RF 有一种机制,可以在通过线路发送时将 bean 属性从服务器实例复制到客户端实例。
我想使用相同的代码在客户端和服务器端对对象进行排序和操作。
但我面临一个问题,因为在客户端我们需要一个代表服务器类的代理接口。
有没有办法在两者中使用相同的接口?我知道 RF 有一种机制,可以在通过线路发送时将 bean 属性从服务器实例复制到客户端实例。
使用相同 API 的一种方法是使用代理扩展和域对象实现的接口。
// common interfaces
interface Foo { … }
interface Bar<T extends Foo> {
int getX();
void setX(int x);
// setters need to use generics
List<T> getFoos();
void setFoos(List<T> foos);
// with only a getter, things get easier:
Bar getParent();
}
// domain objects
class RealFoo implements Foo { … }
class RealBar implements Bar<RealFoo> {
int x;
List<RealFoo> foos;
RealBar parent;
@Override
public RealBar getParent() { return parent; }
// other getters and setters
}
// proxy interfaces
@ProxyFor(RealFoo.class)
interface FooProxy extends Foo { … }
@ProxyFor(RealBar.class)
interface BarProxy extends Bar<FooProxy> {
@Override
BarProxy getParent();
// other getters and setters
}
然后,您可以在客户端和服务器端使用Comparator<Foo>
or Comparator<Bar>
。
我通常只以这种方式实现特征(方面,方面,以你喜欢的方式调用它们) HasId
,而不是完整的域对象的 API。然后我可以用来获取任何对象的键,将它们放入地图或比较是否相等,用于显示(客户端上的自定义、发送到客户端的服务器端错误消息等) ,用于排序等。HasLabel
HasPosition
HasId
HasLabel
Cell
HasPosition
RequestFactory 的要点是它不使用相同的类型。每个请求上下文描述了调用到达服务器时要执行的一组操作(创建和查找内容,然后应用 setter,然后运行服务方法)。由于调用被描述为只是服务器上真实事物的代理,因此您需要一个“假”模型对象,例如 a EntityProxy
orValueProxy
以确保唯一可以进行的调用是 getter 和 setter - 有时,setter 是不允许的(当从服务器读取对象但在编辑之前)。
如果您的模型很简单,即不包含其他对象,而仅包含字符串、日期和原语,您可以让实体和代理都实现相同的接口。但是,如果模型包含子对象,那么这将更加困难 - 唯一可能的方法是忽略那些 getter 和 setter。否则,您不能覆盖代理类型中的那些方法来指定该嵌套对象的代理版本。
如果您确实想在客户端和服务器上重用相同的类型,请考虑使用 RPC istead。
正如 Thomas 在他的回答中所说,当前 GWT 在客户端和服务器中共享代码的唯一方法是在双方实现相同的接口并在您的共享代码中使用它。
正如您在查询中所说,由于 RF 将属性从服务器复制到客户端,理论上我们可以在双方(更简单的代码)使用相同的接口(代理接口),将 @ValueFor 值设置为指向自身。
让我们看一个例子:
// Shared interface in client and server sides
@ProxyFor(Foo.class)
interface Foo extends ValueProxy {
String getBar();
}
// Server side implementation
class FooImpl implements Foo {
String getBar(){return "bar";};
}
作为信息,我们在我们的产品中使用这种方法,因此我们可以销售 2 个后端解决方案(一个基于 GAE,另一个基于 couchdb)。
上面的代码适用于不创建新值的客户端代码,但如果你想创建它们,定义一个值定位器就足够了:
// Say RF which locator to use to create classes in server side
@ProxyFor(value = Foo.class, locator ALocator.class)
interface Foo extends ValueProxy {
}
public class ALocator extends Locator<Foo, String> {
public Foo create(Class<? extends Foo> clazz) {
return new FooImpl();
}
...
}
不幸的是,RF 不处理服务器端的接口,请参阅问题: 7509和5762。
但是,正如您在问题评论中看到的那样,已经有一个解决方案(待审核)。希望它将包含在 GWT 的下一个版本中。
同时,您可以使用这种方法,只需将文件复制到ResolverServiceLayer.java
您的 src 文件夹中并应用此补丁即可。