对于已经在 JSP/JEE 和 HTML/Javascript 方面有丰富经验的人来说,GWT 只需要半天时间就可以理解。但是你需要两个月才能掌握。
以下是关于将技术与 GWT 相结合的建议,我相信这将使您的企业级应用程序成功。我认为您应该使用 GWT,因为它具有可调试性。但是可调试性是有代价的。GWT 调试至少需要一台四核 8GB 的机器。如果您认为这不是真的,那可能是因为您找到了一种使 GWT UI 变得小而简单的方法。
Eclipse 在调试 GWT 应用程序时挂起
RequiresResize、ProvidesResize 和 Layouts
在 GWT 中您需要掌握的第一件事是由接口 RequiresResize、ProvidesResize 规定的简单布局概念。您需要确保从 RootLayoutPanel 到可调整大小的小部件的 RequiresResize/ProvidesResize 链必须不间断。你需要掌握在你的 UI 中构建 RequiresResize/ProvidesResize 的流程。否则,在调整浏览器大小时,您会看到一两个奇怪的悬垂的果实,它们的大小无法调整。
我认为应该不惜一切代价避免为每个小部件编写预定的调整大小而不是依赖于谷歌的 RequiresResize/ProvidesResize。否则,请记住在几次迭代中对调整大小进行去抖动。太多的试验/错误让我无法完善调整大小。
异步异步异步
你需要接受的下一个概念......我没有说“你需要学习”,但“你需要接受”是 Javascript 的异步行为,因此也是 GWT Java 的异步行为。是否使用 GWT 并不重要。您必须习惯于将控制权反转给被调用者以控制调用者的成功响应。
你不能写
List<Persons> persons = server.getData(personId);
你必须屈服于做
server.getData(personId, new Callback<Persons>(){
@override public void onSuccess(Person person){ ..... }
@override public void onFailure(Exception ex){ ..... }
});
你不能写
boolean doOrNot = ConfirmDialogBox();
你必须写
ConfirmDialogBox(new CloseHandler(){
public void onAccept(Person person){ ...}
public void onCancel(){ ... }
});
GWT 是 Java 但不是 Java
我对不断尝试使用 apache 字节码 jar 与 GWT 客户端进行编译的人的存在感到很有趣,GWT 客户端是用 Java 编写的 Javascript。
二进制数据和 GWT
GWT 可视化客户端
我发现最好的组合是 GWT 2.4.0 和 Sencha gxt 2.2.5。
我避免使用 GXT-Uibinder 项目,因为我发现它对 3rd 方 GWT 框架的其他组合施加了不便的限制。特别是那些严重依赖 GWT.create() 生成器的框架。GXT-Uibinder 是 Sencha 之外的一个项目。
GXT 2.2 及以下版本要求我编写包装器以使其可与 uibinder 一起使用,因为我拒绝使用 kludgy GXT-uibinder 项目。由于一个愚蠢的错位,包装器是必要的。任何在 uibinder 中用作父窗口小部件节点的类都必须实现 GWT HasWidgets,这需要实现一个方法返回iterator<Widget>
。不幸的是,GXT 2.2 已经实现了返回错误泛型迭代器的 iterator() 方法。
GXT 3 解决了这个问题。我认为 GXT 3 包含 GXT-uibinder 但您不必使用它。您不必使用 GXT 3 编写太多包装(不使用 GXT-uibinder)即可将其与 uibinder 一起使用。但我发现 GXT 3 仍然有一些古怪的错误行为,试图解决这些问题并不值得我花时间。所以我坚持使用 GXT 2.2.5,直到 GXT 3 稳定下来。
我创建了用于包装 SmartGWT (uibinding-smartgwt) 的谷歌代码项目。SmartGWT 是一个非常自私的框架。如果我尝试将它与 GWT vanilla 混合,我的努力通常会导致灾难。这是由于 SmartClient 和 GWT 的小部件之间存在某种 Z 索引。
如果您出于许可问题决定使用 SmartGWT,则必须确保仅使用 SmartGWT 而不是与任何其他 Widget 提供程序一起使用。甚至没有 GWT 香草。你很可能需要使用我的 uibinding-smartgwt 项目。我正在尝试增强它以使用一些更新的 uibinder 功能并将非可视元素重新定义为不是小部件,但我目前对 GXT 的使用过于复杂,同时考虑这两个框架让我感到困惑。因为他们的行为不同。
尽管 GXT 3 似乎已经使自己与 GWT 完全一致,但 SmartGWT 并没有表现出任何这样做的努力。3rd 方小部件提供者与 GWT 之间的完全对齐,以便它顺利地实现 GWT 的接口是绝对必要的,以避免浪费大量时间不得不在 kludges 之后编写 kludges 以解决一些小的视觉问题。是的,尤其是 ProvidesResize/RequiresResize 架构。
永远不要使用 GWT 孵化。尝试它们,然后尝试使您的项目可维护、可持续和可增强。我们甚至不要去那里。
客户端-服务器通信
不要使用 GWT-RPC。不要。除了学习GWT的方便。
RPC 适用于您无意超出演示阶段和几乎不可用阶段的简单应用程序。不编写分布式/扩展企业级应用程序的程序员可能不会同意我的看法。
单元测试对于开发您的应用程序非常有帮助。首先忘记所有那些单元测试框架。仅仅能够编写一个简单的例程来测试每个小功能而不涉及应用程序的巨大画面是非常重要的。例如,我只想测试骆驼化循环以使其工作。GWT-RPC 给你的正式/非正式单元测试带来极大的不便。
我非常喜欢在 GWT 客户端使用 JAX-RS REST-RPC thro RestGWT和在服务器端使用 RestEasy。我将 JAX-B 与 RestEasy 的 Jackson JSON 处理实现结合使用。您可以尝试使用 Jersey,而不是 Resteasy。
通过这种方式,我可以使用 FireFox REST 客户端来测试独立于 GWT 的服务器。事实上,在客户端使用 GWT 启动项目后,您可以扩展应用程序以使用非 GWT 客户端(如 JQuery)作为 REST 服务的客户端。
REST 还使您可以轻松编写代理/隧道服务器,让您克服浏览器的 SLD-SO-P(“二级域,同源”策略)安全限制。然而,GWT-RPC 的数据格式是故意无法破译和不稳定的(我不明白谷歌工程师在增加安全性背后的想法,因为你仍然可以看到人类可读文本的点点滴滴),我没有尝试写隧道 GWT-RPC 服务的代理。我不知道它有多可行。
http://h2g2java.blessedgeek.com/2011/11/gwt-with-jax-rs-aka-rpcrest-part-0.html。
顺便说一句,克服 sld-sop 的脚本包含是非常糟糕的主意。甚至不要考虑它。
持久性
用于非 GAE 的休眠 JPA。Eclipselink JPA for GAE 与 Google 的 MySQL DataNucleus JPA for GAE 与 Google 数据存储。
最初,我接受了 JDO 的想法。我非常努力,JDO 不断给我带来冲突。我放弃。最初,Google 似乎一直在努力说服我们 JDO 是优秀的 JPA。不管是真是假,到目前为止,我还没有获得使用 JDO 持久性的技能。而且由于我也必须为非 GAE 编程,所以我不想让 JDO 的复杂性影响我的思想。
我提到这个的原因是因为我倾向于使用与 JAX-RS POJO 相同的 JPA POJO。这意味着,我发现 JPA、JAX-RS、JAXB 和 Jackson 注释混合到同一个 POJO-DTO 中,没有冲突。我经常在 GWT 客户端、JAX_RS 服务器和 JPA 持久性之间共享一组 POJO(有一些例外)。要实现这一点,您必须有一个限制——所有 DTO 都必须是 GWT 可序列化的。不仅仅是可序列化的。尽可能避免编写 dto 转换器。浪费时间拥有三组不同的 POJO-DTO,然后在它们之间使用转换器。
MVP
我发现 MVP4G 是一个非常易于管理的 MVP 框架。以下讨论演示了我如何使用 MVP4G:
https://groups.google.com/forum/?fromgroups#!searchin/mvp4g/blessedgeek/mvp4g/T6r7egk-3Kk/Jz-dTqZDeMIJ
MVP 是一种非常有用的模式。因为它可以帮助我区分“关注点”。当您能够分离关注点时,您就可以单独测试和解决问题。它还可以帮助您增强/扩展您的项目,尽可能减少来自应用程序迷宫的其他关注点/模块的干扰/纠缠。
MVP4G 还使单元测试变得容易,因为您可以简单地模拟视图或演示者,或者使用简化的事件总线/状态机来仅调试您需要调试的部分。并且由于它的模块化,您可以轻松避免非测试类的污染,这样您就可以在不破坏生产类的情况下删除测试源树。IOW,您不必修改非测试类来测试它们。