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

我想弄清楚是否应该将我的gwt-rpc调用迁移到新的GWT2.1 RequestFactory cals中。

Google文档隐约提到,RequestFactory是一种更好的“面向数据的服务”的客户端 – 服务器通信方法,

我可以从文档中提炼出来的是,有一个新的代理类可以简化通信(你不会来回传递实际的实体,而只是代理,所以它更轻,更容易pipe理)

这是整个问题还是我在大局中错过了其他的东西?

GWT RPC和RequestFactory之间最大的区别是RPC系统是“RPC-by-concrete-type”,而RequestFactory是“RPC-by-interface”。

开始使用RPC比较方便,因为您在客户端和服务器上都编写了较less的代码行并使用相同的类。 您可以用一堆getter和setter创build一个Person类,也可以使用一些简单的业务逻辑来进一步对Person对象中的数据进行切片。 这很好,直到你想要在你的类中有特定于服务器的,非GWT兼容的代码。 由于RPC系统基于在客户端和服务器上具有相同的具体types,因此您可以根据GWT客户端的functionselect复杂的壁垒。

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

假设你的域对象不会与GWT兼容,那么RequestFactory就开始了。 您只需声明代理接口中客户端代码应读取和写入的属性,然后RequestFactory服务器组件负责封送数据并调用服务方法。 对于具有“实体”或“具有身份和版本的对象”定义明确的概念的应用程序, EntityProxytypes用于将数据的持久标识语义公开给客户端代码。 简单对象使用ValueProxytypes进行映射。

通过使用RequestFactory,您可以支付预先启动成本,以适应比GWT RPC轻松支持的更复杂的系统。 RequestFactory的ServiceLayer通过添加ServiceLayerDecorator实例提供了更多的挂钩来自定义其行为。

我经历了从RPC到RF的转换。 首先,我必须说我的经验是有限的,我使用了许多EntityProxies为0。

GWT RPC的优点:

  • 这很容易设置,理解和学习!
  • 在客户端和服务器上使用相同的基于类的对象。
  • 这种方法可以节省大量的代码。
  • 理想情况下,当在客户端和服务器上使用相同的模型对象(和POJOS)时,POJO ==模型对象== DTO
  • 容易移动的东西从服务器到客户端。
  • 容易共享客户端和服务器之间的通用逻辑的实现(当你需要不同的逻辑时,这可能变成一个关键的缺点)。

Dispvatages of GWT RPC:

  • 不可能有不同的服务器和客户端方法的实现,例如你可能需要在客户端和服务器上使用不同的日志框架,或者不同的equals方法。
  • 真正糟糕的实现不能进一步扩展:大多数服务器function是作为RPC类的静态方法实现的。 这真的很棒。
  • 例如,添加服务器端错误混淆是不可能的
  • 一些安全XSS的关注,不是很优雅的解决,请参阅文档(我不确定这是否更优雅的RequestFactory)

RequestFactory的缺点:

  • 真的很难从官方文档中了解它的优点! 它始于完全误导性的术语PROXIES – 这些实际上是由RF自动创build的RF的DTO。 代理由接口定义,例如@ProxyFor(Journal.class)。 IDE检查日志中是否存在相应的方法。 这么多的映射。
  • 在客户端和服务器的共同点方面,RF对你来说不会有太大的帮助
  • 在客户端上,您需要将“PROXIES”转换为您的客户端域对象,反之亦然。 这完全荒谬。 它可以用几行代码声明地完成,但没有任何支持! 如果只是我们可以更优雅地将我们的域对象映射到代理,那么像JavaScript方法JSON.stringify(.. ,,)就是RF工具箱中的MISSING。
  • 不要忘记,你也是负责设置域对象的可转让的属性代理,等等recursion。
  • 服务器上的POOR ERROR HANDLING和 – 在服务器上默认省略堆栈跟踪,并且在客户端上获得空无用的exception。 即使当我设置自定义error handling程序,我也无法得到低级别的堆栈跟踪! 可怕。
  • IDE支持和其他地方的一些小错误。 我提出了两个被接受的bug请求。 不需要爱因斯坦来弄明白那些实际上是错误的。
  • 文件卡。 正如我所提到的代理应该更好地解释,这个词是错误的。 对于我正在解决的基本常见问题,DOCS是无用的。 另一个来自DOC的误解的例子是JPA注释与RF的连接。 从简洁的文档看来,他们有点玩,是的,在StackOverflow上有一个相应的问题。 我build议在理解RF之前忘记任何JPA“连接”。

RequestFactory的优点

  • 优秀的论坛支持。
  • IDE的支持是相当不错的(但与RPC形成鲜明对照)
  • 您的客户端和服务器实现的灵活性(松耦合)
  • 花哨的东西,连接到EntityProxies,超越简单的DTO – caching,部分更新,非常有用的移动。
  • 您可以使用ValueProxies作为DTO的最简单替代品(但是您必须自己做所有不那么奇怪的转换)。
  • 支持BeanvalidationJSR-303。

综合考虑GWT的其他缺点:

  • 不可能运行集成testing(GWT客户端代码+远程服务器)与提供的JUnit支持<=所有JSNI必须被模拟(例如本地存储),SOP是一个问题。

  • 不支持testing设置 – 无头浏览器+远程服务器<=不对GWT,SOP进行简单的无头testing。

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

  • JSNI是非常强大的,但是在会议上他们给出的那些shiny的演讲中,他们并没有多说这个JSNI代码有一些规则。 再次,搞清楚如何写一个简单的callback是一个值得真正的研究者的任务。

总之,当RPC大多数情况下适合您的需求时,从GWT RPC到RequestFactory的转换远不是WIN-WIN的情况。 您最终将从客户端域对象到代理服务器进行吨转换,反之亦然。 但是,您可以获得一些灵活性和强大的解决scheme。 在论坛上的支持也非常好,星期六也是如此!

考虑到我刚刚提到的所有优点和缺点,事先考虑这些方法是否实际上改善了您的解决scheme和您的开发设置而没有大的取舍。

我发现为我所有的实体创buildProxy类非常烦人。 我的Hibernate / JPA pojos是从数据库模型自动生成的。 为什么现在需要为RPC创build第二个镜像? 我们有一个很好的“评估”框架,照顾“去冬眠”pojos。

另外,定义服务接口的想法并不像Java协议那样将服务器端服务实现为Java协议,而是实现了这些方法 – 听起来对我来说是非常类似于J2EE 1.x / 2.x的。

与RequestFactory的error handling和testingfunction差(因为它处理GWT的大部分内容)不同,RPC允许您使用更多的面向服务的方法。 RequestFactory实现了一个更现代的dependency injection风格的方法,如果你需要调用复杂的多态数据结构,可以提供一个有用的方法。 当使用RPC时,你的数据结构将需要更平坦,因为这将允许你的编组工具在你的json / xml和java模型之间进行转换。 使用RPC还允许您实现更强大的体系结构,正如Google网站上的gwt dev部分所引用的那样。

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

首先考虑服务定义的最直接的方法就是把它们当作应用程序的整个后端。 从这个angular度来看,客户端代码是您的“前端”,服务器上运行的所有服务代码都是“后端”。 如果采取这种方法,那么您的服务实现将倾向于更通用的API,而不是与特定的应用程序紧密耦合。 您的服务定义可能会直接通过JDBC或Hibernate访问数据库,甚至直接访问服务器文件系统中的文件。 对于许多应用程序来说,这个视图是合适的,它可以非常有效,因为它减less了层数。

多层部署

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

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

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

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

总而言之,在使用两者之后,现在我总是使用RPC作为更轻量级的,更容易testing和debugging的,并且使用RequestFactory更快。 虽然RequestFactory可能更优雅,可扩展的RPC计数器部分。 增加的复杂性并不能使它成为一个更好的工具。

我认为最好的架构是使用两个Web应用程序,一个客户端和一个服务器。 服务器是一个使用servlet.jar库的简单轻量级通用java web应用程序。 客户端是GWT。 您通过GWT-RPC将RESTful请求发送到客户端Web应用程序的服务器端。 客户端的服务器端只是一个传递给Apache的HTTP客户端,它使用一个持久的隧道进入你的服务器servlet Web应用程序中作为单个servlet运行的请求处理程序。 servlet Web应用程序应该包含数据库应用程序层(hibernate,cayenne,sql等)。这允许您从实际的客户端完全离开数据库对象模型,从而提供更加可扩展和可靠的方法来开发和testing您的应用程序。 授予它需要一点点初始设置时间,但最终允许您创build一个dynamic的请求工厂坐在GWT之外。 这可以让你充分利用两全其美。 更不用说能够testing和更改您的服务器端,而无需gwt客户端编译或构build。

如果你在客户端有一个沉重的pojo,例如,如果你使用Hibernate或者JPA实体,我认为这是非常有帮助的。 我们采用了另一种解决scheme,使用了一个Django风格的持久性框架,其实体非常轻巧。

唯一需要注意的是RequestFactory使用二进制数据传输(deRPC也许?)而不是普通的GWT-RPC。

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

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

问候丹尼尔

公平地说,当考虑一个有限的MIS应用程序,比如10到20个CRUD可能的业务对象,并且每一个具有1-10个属性时,真的是个人喜好哪条路要走?

如果是这样,那么可能预测你的应用程序将如何扩展可能是select你的路由GWT RPC或RequestFactory的关键:

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

  2. 我的应用程序将在实体的广度上显着增加,但每个参与者的相对数量仍然很低。 5000个对象* 100个logging。

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

就我而言,我正在试图做出这个决定的起点。 由于不得不改变UI客户端结构以及进行交通select而变得更复杂。 我以前(很大程度上)大规模的GWT用户界面使用了Hmvc4Gwt库,该库已被GWT MVP工具所取代。