什么时候应该使用RequestFactory和GWT-RPC?

时间:2010-11-07 21:45:05

标签: gwt gwt-rpc requestfactory

我想知道是否应该将我的gwt-rpc调用迁移到新的GWT2.1 RequestFactory cals。

Google文档模糊地提到RequestFactory是一种更好的客户端 - 服务器通信方法,用于“面向数据的服务”

我可以从文档中提炼出来的是,有一个新的Proxy类可以简化通信(你不会来回传递实际的实体而只是代理,因此重量更轻,更容易管理)< / p>

这是重点还是我在大局中遗漏了其他东西?

8 个答案:

答案 0 :(得分:73)

GWT RPC和RequestFactory之间的最大区别在于RPC系统是“RPC-by-concrete-type”,而RequestFactory是“逐个接口”。

RPC更方便入门,因为您编写的代码行较少,并且在客户端和服务器上使用相同的类。您可以使用一堆getter和setter创建一个Person类,也可以使用一些简单的业务逻辑来进一步切片和切割Person对象中的数据。这很有效,直到你想要在你的类中拥有特定于服务器,非GWT兼容的代码。因为RPC系统基于客户端和服务器上具有相同的具体类型,所以您可以根据GWT客户端的功能来打击复杂性墙。

为了避免使用不兼容的代码,许多用户最终会创建一个对等PersonDTO,它会隐藏服务器上使用的真实Person对象。 PersonDTO只有服务器端“域”,Person对象的getter和setter的子集。现在,您必须编写在PersonPersonDTO对象以及要传递给客户端的所有其他对象类型之间编组数据的代码。

RequestFactory首先假设您的域对象不会与GWT兼容。您只需在Proxy接口中声明应由客户端代码读取和写入的属性,并且RequestFactory服务器组件负责封送数据并调用您的服务方法。对于具有明确定义的“实体”或“具有标识和版本的对象”概念的应用程序,EntityProxy类型用于将数据的持久标识语义暴露给客户端代码。使用ValueProxy类型映射简单对象。

使用RequestFactory,您需要支付前期启动成本,以容纳比GWT RPC轻松支持的更复杂的系统。 RequestFactory的ServiceLayer提供了更多的钩子来通过添加ServiceLayerDecorator个实例来自定义其行为。

答案 1 :(得分:28)

我经历了从RPC到RF的过渡。首先,我必须说我的经验是有限的,我使用了尽可能多的EntityProxies。

GWT RPC的优点:

  • 设置,理解和学习非常容易!
  • 在客户端和服务器上使用相同的基于类的对象。
  • 这种方法可以节省大量代码。
  • 理想,当在客户端和服务器上使用相同的模型对象(和POJOS)时,POJO == MODEL OBJECTs == DTOs
  • 轻松将内容从服务器移动到客户端。
  • 易于在客户端和服务器之间共享通用逻辑的实现(当您需要不同的逻辑时,这可能会成为一个关键的缺点)。

GWT RPC的缺点:

  • 无法为服务器和客户端实现某些方法的不同实现,例如:您可能需要在客户端和服务器上使用不同的日志框架,或者使用不同的equals方法。
  • 真正无法进一步扩展的BAD实现:大多数服务器功能都是作为RPC类上的静态方法实现的。真的很糟糕。
  • e.g。添加服务器端错误混淆
  • 是不可能的
  • 某些安全性XSS问题并不是很容易解决,请参阅docs(我不确定这对RequestFactory来说是否更优雅)

RequestFactory的缺点:

  • 真的很难从官方文件中了解它的优点是什么!它始于完全误导性的术语PROXIES - 这些实际上是由RF自动创建的RF的DTO。代理由接口定义,例如@ProxyFor(Journal.class)。 IDE检查Journal上是否存在相应的方法。这么多的映射。
  • 就客户端和服务器的共性而言,RF对您没有太大帮助,因为
  • 在客户端,您需要转换&#34; PROXIES&#34;到您的客户端域对象,反之亦然。这完全是荒谬的。它可以在几行代码中以声明方式完成,但是没有任何支持!如果我们只能更优雅地将我们的域对象映射到代理,那么像JavaScript方法JSON.stringify(.. ,,)这样的东西在RF工具箱中就是MISSING。
  • 不要忘记您还负责将域对象的可转移属性设置为代理,依此递归。
  • 服务器上的错误处理和 - 服务器上默认省略堆栈跟踪,并且您在客户端上获得空的无用例外。即使我设置自定义错误处理程序,我也无法获得低级别的堆栈跟踪!可怕。
  • IDE支持和其他地方的一些小错误。我提交了两个被接受的错误请求。不是爱因斯坦需要弄清楚那些实际上是错误。
  • 文件说话。正如我所提到的,应该更好地解释代理,这个术语是MISLEADING。对于我正在解决的基本常见问题,DOCS是无用的。来自DOC的误解的另一个例子是JPA注释与RF的连接。从简洁的文档看,它们有点一起玩,是的,StackOverflow上有一个相应的问题。我建议忘记任何JPA&#39;连接&#39;在了解RF之前。

RequestFactory的优点

  • 优秀的论坛支持。
  • IDE支持相当不错(但与RPC相比并不是一个优势)
  • 客户端和服务器实现的灵活性(松散耦合)
  • 除了简单的DTO之外,连接到EntityProxies的花哨的东西 - 缓存,部分更新,对移动设备非常有用。
  • 您可以使用ValueProxies作为DTO的最简单替代品(但您必须自己做所有不那么花哨的转换)。
  • 支持Bean验证JSR-303。

考虑GWT的其他缺点:

  • 无法使用提供的JUnit支持运行集成测试(GWT客户端代码+远程服务器)&lt; =必须模拟所有JSNI(例如localStorage),SOP是个问题。

  • 不支持测试设置 - 无头浏览器+远程服务器&lt; =没有针对GWT,SOP的简单无头测试。

  • 是的,可以运行selenium集成测试(但这不是我想要的)

  • JSNI是非常强大的,但是在他们在会议上发表的那些闪亮的演讲中,他们并没有太多谈论编写JSNI代码还有一些规则。再次,弄清楚如何编写一个简单的回调是一个值得真正研究者的任务。

总之,从GWT RPC到RequestFactory的转换远非WIN-WIN情况,  当RPC主要满足您的需求时。您最终会将客户端域对象的吨转换写入代理,反之亦然。但是,您可以获得解决方案的一些灵活性和稳健性。周六,论坛上的支持也很棒!

考虑到我刚才提到的所有优点和缺点,提前考虑这些方法中的任何一种是否真正改善了您的解决方案和您的开发设置而没有大的权衡取舍,这是非常好的。

答案 2 :(得分:6)

我发现为我的所有实体创建代理类非常讨厌。我的Hibernate / JPA pojos是从数据库模型自动生成的。为什么我现在需要为RPC创建第二个镜像?我们有一个很好的“estivation”框架,负责“去冬眠”pojos。

此外,定义服务接口的想法并没有完全实现服务器端服务作为java合同但是实现了这些方法 - 听起来非常像J2EE 1.x / 2.x.

答案 3 :(得分:4)

与RequestFactory不同,它具有较差的错误处理和测试功能(因为它处理GWT引擎盖下的大部分内容),RPC允许您使用更加面向服务的方法。 RequestFactory实现了一种更现代的依赖注入样式方法,如果需要调用复杂的多态数据结构,它可以提供一种有用的方法。使用RPC时,您的数据结构将需要更加平坦,因为这将允许您的编组实用程序在您的json / xml和Java模型之间进行转换。使用RPC还可以实现更强大的架构,如Google网站上的gwt dev部分所述。

“简单的客户端/服务器部署

考虑服务定义的第一个也是最直接的方法是将它们视为应用程序的整个后端。从这个角度来看,客户端代码是您的“前端”,在服务器上运行的所有服务代码都是“后端”。如果采用这种方法,您的服务实现往往是更通用的API,而不是紧密耦合到一个特定的应用程序。您的服务定义可能会直接通过JDBC或Hibernate访问数据库,甚至可以直接访问服务器文件系统中的文件。对于许多应用程序,此视图是合适的,并且它可以非常有效,因为它减少了层数。

多层部署

在更复杂的多层体系结构中,您的GWT服务定义可能只是轻量级网关,可以调用后端服务器环境(如J2EE服务器)。从这个角度来看,您的服务可以被视为应用程序用户界面的“服务器一半”。服务是为用户界面的特定需求而创建的,而不是通用的。您的服务成为“后端”类的“前端”,这些类通过将调用拼接到一个更通用的后端服务层来编写,例如,作为J2EE服务器集群实现。如果您需要后端服务在与HTTP服务器不同的物理计算机上运行,​​那么这种架构是合适的。“

另请注意,设置单个RequestFactory服务需要创建大约6个左右的java类,而RPC只需要3个。更多代码==更多错误和复杂性在我的书中。

RequestFactory在请求处理期间也有一些额外的开销,因为它必须编组数据代理和实际java模型之间的序列化。这个添加的界面增加了额外的处理周期,可以真正在企业或生产环境中添加。

我也不相信RequestFactory服务是像RPC服务那样的序列化。

总而言之,在使用了两段时间之后,我总是使用RPC,因为它更轻量级,更容易测试和调试,并且使用RequestFactory更快。虽然RequestFactory可能比它的RPC计数器部分更优雅和可扩展。增加的复杂性并不能使其成为必要的更好的工具。

我的观点是,最好的架构是使用两个Web应用程序,一个客户端和一个服务器。服务器是一个使用servlet.jar库的简单轻量级通用java webapp。客户端是GWT。您通过GWT-RPC将RESTful请求发送到客户端Web应用程序的服务器端。客户端的服务器端只是传递给apache http客户端,它使用持久隧道进入您在服务器servlet Web应用程序中作为单个servlet运行的请求处理程序。 servlet Web应用程序应包含您的数据库应用程序层(hibernate,cayenne,sql等)。这允许您将数据库对象模型与实际客户端完全分离,从而提供更加可扩展且可靠的方式来开发和单元测试应用程序。当然,它需要一点点初始设置时间,但最终允许您创建一个位于GWT之外的动态请求工厂。这使您可以充分利用两全其美。更不用说能够在不必编译或构建gwt客户端的情况下测试和更改服务器端。

答案 4 :(得分:0)

我认为如果你在客户端有一个沉重的pojo,例如你使用Hibernate或JPA实体,那将非常有用。 我们采用了另一种解决方案,使用具有非常轻的实体的Django样式持久性框架。

答案 5 :(得分:0)

我要提出的唯一警告是RequestFactory使用二进制数据传输(deRPC可能?)而不是普通的GWT-RPC。

这只有在您使用SyncProxy,Jmeter,Fiddler或任何可以读取/评估HTTP请求/响应内容的类似工具(如GWT-RPC)进行大量测试时才有意义,但是对于deRPC来说会更具挑战性或RequestFactory。

答案 6 :(得分:0)

我们的项目中有一个非常大的GWT-RPC实现。 实际上我们有50个Service接口,每个接口都有很多方法,我们在编译器生成的TypeSerializers大小方面存在问题,这使得我们的JS代码变得庞大。 所以我们正在分析以转向RequestFactory。 我已经阅读了几天深入网络并试图找到其他人正在做的事情。 我看到的最重要的缺点,也许我可能是错的,使用RequestFactory,您不再能够控制Server Domain对象与客户端对象之间的通信。 我们需要的是以受控方式应用加载/保存模式。我的意思是,例如客户端接收属于特定事务的对象的整个对象图,做他的更新并将它们全部发送回服务器。服务器将负责进行验证,将旧值与新值进行比较并保持持久性。如果来自不同站点的2个用户获得相同的事务并进行一些更新,则生成的事务不应是合并的事务。其中一个更新应该在我的方案中失败。 我没有看到RequestFactory有助于支持这种处理。

此致 丹尼尔

答案 7 :(得分:0)

公平地说,在考虑有限的MIS应用程序时,例如10-20个CRUD可用的业务对象,并且每个具有~1-10个属性,这真的是个人偏好要使用哪条路径?< / p>

如果是这样,那么预测应用程序的扩展方式可能是选择路由GWT RPC或RequestFactory的关键:

  1. 我的申请预计将保留相对有限数量的实体,但会在数量方面大幅增加。 10-20个对象* 100,000个记录。

  2. 我的应用程序将在实体的广度上显着增加,但每个实体的相关数量将保持较低。 5000个对象* 100条记录。

  3. 我的申请预计将保留在相对有限数量的实体中,并将​​保持相对较低的数量,例如10-20个对象* 100条记录

  4. 就我而言,我正处于尝试做出这个决定的起点。由于必须改变UI客户端架构以及进行传输选择而变得更加复杂。我之前(显着)大规模GWT UI使用了Hmvc4Gwt库,该库已被GWT MVP设施取代。