从2007.08进入项目到2008.11产品正式运营,经历了两个GWT项目开发(这两个项目共享相同widget)。基本全程都很顺利。现在分享一下开发历程和注意事项。
开发环境: ubuntu7.10 + apache php + jboss.
下面是开发总结:
1: GWT Version & Upgrade
得到一份(新)版本后,你得作如下的工作:
1)看看支持哪些功能和特性
2)看看修正了哪些bug
3)看看屏蔽了哪些function
4)更新相关的编译,运行脚本
这通常是很有用的。比如, 一开始就知道GWT支持国际化这是非常重要的。还有就是
需要知道支持哪些java package, classes, 以及jdk版本和语法特性。这比编译通不过,再来反复修改,要节省大量时间。另外,版本的升级,部分代码需要跟着同步。 比如,
GWT 1.4.2 如果想让一个Popup在 browser居中,得自己另外写方法。 GWT 1.4.6就提供
popupPanel.center()直接支持。 GWT1.6.9时float类型已经不被支持,需要进行相应替换才能编译通过。
2:系统配置项:
1)XML Schema(怎么取得这些数据,参考下面的Ajax设计模式)
2)Http header. 比如:
<head>
<!-- HB, 2008/09/09 -->
<meta id="require-logged-in" name="required" content="false"/>
</head>
取得这些数据的方法:
public static String getMetaContentValueById(String metaTagId,String defaultValue){
String result = null;
try{
Element elem = DOM.getElementById(metaTagId);
result = DOM.getElementAttribute(elem, CommonDefn.LOCALE_TOKEN);
result = (result == null) ? defaultValue : result;
result = (result.trim().length() < 1) ? defaultValue : result;
}
catch(Exception e) {
result = defaultValue;
}
return result;
}
3:完全组件化开发
自认为分模块(module)开发是不必要的,而且编译的开销特别大。
我们主要的分页面(Page)架构是基于History(Listener)的。从一个页面到另一个页面的代码页很简单: History.newItem(_link); GoBack也很简单: History.back();
这样的架构的一个额外好处,还解决了Ajax的go back问题。 我们可以判断一个页面是通过正常的路径来的,还是通过go back来的。 这样就可以分别对待处理。
4:JSNI & JavaScript
1) 直接写javascript function,供页面或flash 调用
2)使用JSNI作多语言(英文,繁体,简体) 的选择
protected class HyperlinkCommand implements Command {
protected String _url = "";
public HyperlinkCommand(String url) {
_url = url;
}
/**
* Redirects the browser to the given URL.
* The following is an inline javascript:
* $wnd is the handler for the browser
* .location.href is the relative url
*/
private native void link(String url) /*-{
$wnd.location.href = url;
}-*/;
public void execute() {
link(_url + CommonDefn.HTML_PAGE_SEPARATOR + History.getToken()); // the language link follows by the original page
}
}
5:架构属于你自己的RPC & Servlet.
方便及时修改,测试(在eclipse里运行测试或debug),发布(考虑css兼容问题,你得在自己的browser测试).
Service部分: 采用一个Servlet来作集中控制。前端发送两个参数到Server, I.E.
/proxy/proxy.php?proxyinstr=getavailmovies&jsondto={"uusystemlanguageid":"1", "uuxxx":"1"}
Main.gwt.xml的
<servlet path='/proxy/proxy.php' class='xxxx.debug.proxy.HttpProxy'/>
注意上面的class部分,他不在client包中,这也是我们想要的效果。 这个只供测试RPC用.
而httpProxy,是标准的Servlet.
public class HttpProxy extends HttpServlet {
public void doGet(HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws ServletException, IOException {
doPost(httpRequest, httpResponse);
}
/**
* Process POST requests
*/
public void doPost (HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws ServletException, IOException {
...
}
}
之所以把这个包命名为debug,只是为了在eclipse里运行的时候debug rpc. 它是不会被编译输出到www的。
当在Browser(Firefox,以后简称FF)运行的时候,实际是访问Apache的php,而不是自己建立的Servlet(它负责把数据直接转发到8080的jboss). 而proxy.php也正是作这件事,把80端口的请求转发给8080的jboss的一个Servlet.这就是架构的巧妙之处。
技巧: 在apache下建立soft link到 开发环境下的目录(编译后生成的),就少了N次的cp to apache .
6:Server与Client的约定(term)
1)共享一份相同的常量,定义在各自的CommonDefn中。 i.e.
public interface CommonDefn {
public static final int PERMISSIONS_CHECKOUT = 0x02000000;
}
如果一方有修改,另一方需要同步。
2)由于双方都是用json交换数据,所以对于每个请求,它的json要稳定。如果Server端准备
返回的json有变化,则要同步client。一般数据库的设计发生变化,则要修改Server端。 Server的变化,则带来Client的同步变化。因此,数据库设计决定了整个project的可维护性。
3)Client 与 Server共同维护 (自定义的) Session
4)在Client的CallbackHandler中,如果收到"Session expired!"的 json message, 则需要要求用户(重)登录
5)Client做数据的sort,cache还是Server做? 最后还是Server做。唯一原因是:考虑GWT最终输出是html, js. 精简client始终是整个开发流程都要遵守的规则。
7:Ajax设计模式
1)读取本站的XML
HTTPRequest.asyncGet(_xmlFile, new ResponseTextHandler() {
public void onCompletion(String responseText) {
// In the real world, this text would come as a RPC response. This
// technique is great for testing and samples though!
renderXML(responseText);
}
2)一次发送多条请求(以后称指令),待所有请求完成之后,再作处理。这样能减少指令间的耦合度。
处理方式,每一条指令返回后,在callBack中把计数加1,当所有的计数达到指令的条数后,再作具体的处理。
3)go back问题。我们用public class HistoryStack extends Stack {}的一个
SingleTon的实例来记录页面的流入,流出。来达到HTML Referrer的效果。 也就是说,能够
知道当前页面是来自于哪个页面,在此基础上,再判断是否是goback到达的。然后再作处理
4)TimeOut问题。 网络的延迟,中断,甚至处理时间超过指定的等待时间,都可能引发TimeOut问题。如果你开发的是嵌入式系统。这个问题,就得慎重考虑。目前我们的处理方式:客户端触发的TimeOut处理,我们转入到一个固定页面,这个页面显示:系统正在维护中。 这个页面会定时连接server,当连接成功,重置到index page. 另外,服务端与客户端维持一个
heartbeat,如果检查到一定时间没有(heartbeat),就重新启动client.
8:GWT & 动画效果 以及 Flash
1)用GWT开发动画效果,是很容易的。记住,GWT既面向Widget,也面向DOM.
2)Flash与GWT通讯这里不多说 . 在linux下的FF, Flash可能会跳出来,挡住Popup, alert,menu 也就是说transparent特性无效。如果含有的Flash较多,这简直就是灾难。 我们采取的做法,以Flash挡住Popup为例子,我们采取FlashAnimation来显示Flash,FlashPopupManager来管理Flash与Popup的关系。以两个Popup(上面都有Flash)先后显示为例子.第2个Popup(上层的)显示的时候,把第一个Popup的Flash隐藏。第2个Popup关闭的时候,再显示第一层的flash.这是workaround.然而很有效。 算法采用Stack.
9:异常处理
1)GWT提供全局的异常处理(也就是说能够捕获未被处理的异常), I.E.
// set uncaught exception handler, we should log exception for investigation
GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
public void onUncaughtException(Throwable e) {
// TODO
// should call instruction for error message logging
e.printStackTrace();
Window.alert("Uncaught exception:\n" + e);
// String message = "";
// message += "GWT.getHostPageBaseURL(): " + GWT.getHostPageBaseURL();
// message += "GWT.getModuleBaseURL(): " + GWT.getModuleBaseURL();
// message += "GWT.getModuleName(): " + GWT.getModuleName();
// message += "GWT.isScript(): " + GWT.isScript();
// Window.alert("GWT message:\n" + message);
}
});
2)局部处理,同java一样: try, catch, finally block.
10:加入第三方module(通常也是直接或间接由GWT开发)
1)注意版本的匹配和同步升级
2)在project.gwt.xml中加入模块 . I.E
. <inherits name='com.allen_sauer.gwt.voices.gwt-voices' />
3)在编译和运行的脚本中加入这些library的path
11:多个Project(在同一个目录下)共享widget(不同于上面说的引入module方式)
1)设置各自的project.gwt.xml,以及配置里面的servlet path
2)在client Package下建立各自的EntryPoint Class
3)在public Folder下建立各自的Host web File
4)建立各自的编译(project-compile),运行(project-shell)脚本
分享到:
相关推荐
总结来说,GWT通过Java语言为Web开发提供了一种高效且易维护的解决方案,它简化了前端开发的复杂性,使得开发者可以专注于业务逻辑和用户体验,而无需深入学习多种Web技术。GWT-EXT则进一步增强了GWT在界面设计上的...
- 安装GWT Eclipse Plugin,以便更好地支持GWT项目的创建、编译和调试。 - 可以通过Eclipse的市场(Install New Software)安装GWT Plugin。 #### 三、GWT开发基础 1. **基本概念**: - **模块(Module)**: GWT项目...
- **模块化**:GWT项目如何组织成模块,以及如何使用GWT编译器进行模块的编译和优化。 - **本地存储和持久化**:利用GWT处理浏览器的本地存储,以及如何实现数据的持久化。 - **国际化和本地化**:如何在GWT应用中...
根据给定的信息,我们可以总结并深入探讨以下几个与GWT项目开发相关的知识点: ### 1. 使用GWT实现在Web中实现上下文菜单(右键菜单、弹出菜单) #### 实现背景 在Web应用程序中,默认情况下点击鼠标右键会出现一...
总结,通过阅读《GWT揭秘》试读章节,我们可以了解到GWT项目的运行和调试方法,以及Java调试的重要性。对于GWT开发者来说,理解并掌握这些技术将极大地提升开发效率和产品质量。同时,文档“java_debug调试.doc”将...
总结,GWT作为一个强大的JavaScript开发框架,为Web开发者提供了使用Java进行前端开发的可能性,通过其丰富的功能和优化机制,能够构建高效、可维护的Web应用程序。在初次接触GWT时,理解其特点、工作原理以及如何...
总结,GWT部署涉及了Java开发环境的设置、GWT模块的构建、应用打包、Servlet容器的配置以及部署后的测试和优化。对于"activiti-sample",学习者可以通过它深入了解如何在GWT应用中实现工作流管理。
4. 在GWT项目中运行`gwt:run`命令,浏览器会自动启动并加载应用。 总结来说,"firefox和对应gwt插件"涉及的是Firefox浏览器与GWT Developer Plugin的集成,该插件是GWT开发者在Firefox上进行高效开发和调试的关键...
使用Eclipse或IntelliJ IDEA等集成开发环境(IDE)可以方便地创建和管理GWT项目。 2. **创建第一个GWT应用**: 通过IDE创建一个新的GWT模块,编写简单的Hello World程序,了解基本的Widget使用和布局管理。 3. **理解...
GWT 1.3.1发布于2007年,是GWT项目的一个关键迭代。该版本增强了对AJAX的支持,提供了一套完整的开发框架,包括丰富的UI组件库、调试工具以及优化的编译机制。在Windows平台上,GWT的部署和开发流程与在其他操作系统...
在开发HTML5游戏时,PlayN和GWT(Google Web Toolkit)是...总结来说,通过结合PlayN和GWT,开发者可以使用熟悉的Java语言高效地开发跨平台的HTML5游戏。了解和掌握这两个工具的使用,将极大地提升游戏开发效率和质量。
projectCreator 用于创建 Eclipse 项目的基础结构和 Ant 构建文件,applicationCreator 用于生成基本应用和开发环境,而 junitCreator 则帮助生成 JUnit 测试代码。 【环境准备与应用开发】 在开始 GWT 开发前,...
3. **配置项目结构**:GWT项目通常包含`src/main/java`和`src/main/resources`等目录,用于存放Java源代码和资源文件。你还需要配置`war`目录,这是Web应用的根目录,包含HTML、CSS、JavaScript以及GWT编译后的输出...
总结,SmartGWT 3.1是一个强大而灵活的开发框架,其丰富的组件库、便捷的API、优化的性能和详尽的示例,使得开发高质量的RIA变得更为容易。无论是初学者还是经验丰富的开发者,都能从中受益,提升开发效率和应用质量...
总结起来,GWTDemo项目是一个关于使用Google Web Toolkit开发Web应用的实例,涵盖了GWT的许多核心特性,如用户界面组件、事件处理、异步通信、本地存储、国际化、样式主题以及测试。通过学习和理解这个项目,开发者...