87

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

谷歌文档含糊地提到 RequestFactory 是一种更好的“面向数据的服务”的客户端-服务器通信方法

我可以从文档中提取的是,有一个新的 Proxy 类可以简化通信(您不需要来回传递实际实体,而只是传递代理,因此它更轻且更易于管理)

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

4

8 回答 8

73

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

RPC 上手更方便,因为您编写的代码行数更少,并且在客户端和服务器上使用相同的类。您可能会创建一个Person包含一堆 getter 和 setter 的类,也许还有一些简单的业务逻辑,用于进一步对Person对象中的数据进行切片和切块。这非常有效,直到您最终想要在您的类中拥有特定于服务器的、非 GWT 兼容的代码。由于 RPC 系统基于在客户端和服务器上具有相同的具体类型,因此您可能会根据 GWT 客户端的功能遇到复杂性墙。

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

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

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

于 2011-02-07T20:55:29.560 回答
28

我经历了从 RPC 到 RF 的过渡。首先我不得不说我的经验是有限的,我使用的 EntityProxies 和 0 一样多。

GWT RPC 的优点:

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

GWT RPC 的缺点:

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

RequestFactory 的缺点:

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

RequestFactory 的优势

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

总体上考虑 GWT 的其他缺点:

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

  • 不支持测试设置 - 无头浏览器 + 远程服务器 <= 不支持 GWT、SOP 的简单无头测试。

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

  • JSNI 非常强大,但是在他们在会议上发表的那些闪亮的演讲中,他们并没有过多地谈论编写 JSNI 代码也有一些规则。同样,弄清楚如何编写简单的回调是值得真正的研究人员完成的任务。

总而言之,从 GWT RPC 到 RequestFactory 的过渡远非双赢局面,此时 RPC 最适合您的需求。您最终会编写从客户端域对象到代理的大量转换,反之亦然。但是您的解决方案具有一定的灵活性和稳健性。论坛上的支持非常好,周六也是如此!

考虑到我刚才提到的所有优点和缺点,提前考虑这些方法中的任何一种是否真的可以改进您的解决方案和您的开发设置,而无需进行重大权衡,这是非常值得的。

于 2012-07-23T23:11:54.937 回答
6

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

此外,定义服务接口的想法并不完全将服务器端服务实现为 java 契约,但确实实现了方法 - 对我来说听起来非常 J2EE 1.x/2.x。

于 2010-12-14T02:33:38.397 回答
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 向客户端 Web 应用程序的服务器端发出 RESTful 请求。客户端的服务器端只是通过 apache http 客户端,它使用持久隧道进入您在服务器 servlet Web 应用程序中作为单个 servlet 运行的请求处理程序。servlet web 应用程序应该包含您的数据库应用程序层(hibernate、cayenne、sql 等)。这允许您将数据库对象模型与实际客户端完全分离,从而为开发和单元测试您的应用程序提供更可扩展和更健壮的方法。当然,它需要一点初始设置时间,但最终允许您创建一个位于 GWT 之外的动态请求工厂。这使您可以利用两全其美。更不用说无需编译或构建 gwt 客户端即可测试和更改服务器端。

于 2012-08-02T15:26:18.937 回答
0

公平地说,当考虑一个有限的 MIS 应用程序时,比如说有 10-20 个可 CRUD 的业务对象,每个具有约 1-10 个属性,这真的取决于个人喜好选择哪条路线吗?

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

  1. 我的应用程序预计将保留相对有限数量的实体,但它们的数量将大幅增加。10-20 个对象 * 100,000 条记录。

  2. 我的申请将在实体的广度上显着增加,但每个实体所涉及的相对数量将保持较低水平。5000 个对象 * 100 条记录。

  3. 我的应用程序预计将保留相对有限数量的实体,并且将保持相对较少的数量,例如 10-20 个对象 * 100 条记录

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

于 2012-05-30T17:29:17.397 回答
0

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

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

于 2011-01-17T14:49:52.813 回答
0

我认为如果您在客户端有大量 pojo,例如如果您使用 Hibernate 或 JPA 实体,这真的很有帮助。我们采用了另一种解决方案,使用带有非常轻量实体的 Django 风格的持久性框架。

于 2010-11-23T10:58:12.647 回答
0

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

问候丹尼尔

于 2011-08-18T16:20:01.610 回答