上面的步骤中,我们已经完成第一个GWT应用的编译和测试,下面我们来详细的介绍一下GWT应用开发过程中涉及的几个文件:显示页面HelloWorld.html、主类HelloWorld和配置文件HelloWorld.gwt.xml。
1. 显示页面HelloWorld.html
GWT应用中的HTML内容必须存放在public目录下,public目录的全路径是"org\vivianj\gwt\ublic",是将主类HelloWorld的包名"org.vivianj.gwt.client"中的client替换为"public"后形成的目录结构。
我们将主要介绍HelloWorld.html中和GWT相关的内容,HelloWorld.html文件的全部内容见清单1。
24. <meta name='gwt:module' content='org.vivianj.gwt.HelloWorld'>
|
在HelloWorld.html文件的第24行,我们使用meta标签指定了本页面和GWT模块" org.vivianj.gwt.HelloWorld"之间的联系,meta标签的name属性是不变的,而content属性则是GWT主类全名(org.vivianj.gwt.client.HelloWorld)去掉其中的"client."后的结果。
40. <script language="javascript" src="gwt.js"></script>
|
在HelloWorld.html文件的第40行,我们使用script标记引入GWT工具提供的默认函数库。根据HTML语言的规定,我们可以选择在<head></head>之间加入这行代码,也可以选择在<body></body>之间加入这段代码。GWT建议在<head></head>之间加入这行代码,以便获得稍微快一些的起动速度。
56. <td id="slot1"></td><td id="slot2"></td>
|
在HelloWorld.html文件的第56行,我们使用td标签定义了两个相邻的表格单元格,他们分别命名为"slot1"和"slot2",根据"HelloWorld!"例子的要求,名为"slot1"的单元格中应该显示按钮,而名为"slot2"的单元格中则根据情况决定显示"HelloWorld!"字符串或者不显示任何内容。
我们将在主类HelloWorld.java的源代码中使用RootPanel.get("slot1")来获得对该单元格的引用,请参考下面的"主类HelloWorld"部分的说明。
43. <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
|
在HelloWorld.html的第43行,我们使用iframe标签来设置当前页支持历史功能,iframe的属性必须和上面的内容保持一致,否则将不会起到任何效果。
1. <html>
2. <head>
3.
4. <!-- -->
5. <!-- Any title is fine -->
6. <!-- -->
7. <title>Wrapper HTML for HelloWorld</title>
8.
9. <!-- -->
10. <!-- Use normal html, such as style -->
11. <!-- -->
12. <style>
13. body,td,a,div,.p{font-family:arial,sans-serif}
14. div,td{color:#000000}
15. a:link,.w,.w a:link{color:#0000cc}
16. a:visited{color:#551a8b}
17. a:active{color:#ff0000}
18. </style>
19.
20. <!-- -->
21. <!-- The module reference below is the link -->
22. <!-- between html and your Web Toolkit module -->
23. <!-- -->
24. <meta name='gwt:module' content='org.vivianj.gwt.HelloWorld'>
25.
26. </head>
27.
28. <!-- -->
29. <!-- The body can have arbitrary html, or -->
30. <!-- you can leave the body empty if you want -->
31. <!-- to create a completely dynamic ui -->
32. <!-- -->
33. <body>
34.
35. <!-- -->
36. <!-- This script is required bootstrap stuff. -->
37. <!-- You can put it in the HEAD, but startup -->
38. <!-- is slightly faster if you include it here. -->
39. <!-- -->
40. <script language="javascript" src="gwt.js"></script>
41.
42. <!-- OPTIONAL: include this if you want history support -->
43. <iframe id="__gwt_historyFrame"
style="width:0;height:0;border:0"></iframe>
44.
45. <h1>HelloWorld</h1>
46.
47. <p>
48. This is an example of a host page for the HelloWorld application.
49. You can attach a Web Toolkit module to any HTML page you like,
50. making it easy to add bits of AJAX functionality to existing
pages
51. without starting from scratch.
52. </p>
53.
54. <table align=center>
55. <tr>
56. <td id="slot1"></td><td
id="slot2"></td>
57. </tr>
58. </table>
59. </body>
60. </html>
|
2. 主类HelloWorld
主类HelloWorld必须继承自com.google.gwt.core.client.EntryPoint类,并且覆盖其public void onModuleLoad()方法。
在onModuleLoad()方法中,我们使用GWT中提供的默认显示组件(比如Button)和组装组件(比如VerticalPanel)来设计需要显示的界面,所有这些组件都位于com.google.gwt.user.client.ui包下面。这些组件的命名规则和Java AWT的命名规则基本类似,使用方式也和AWT的基本一致,不过GWT中提供了不少的新组建可供选择,比如可以直接用VerticalPanel来实现垂直方向的布局管理。
HelloWorld.java中的19和20行,就声明了Button和Label两个显示组件。
19. final Button button = new Button("Click me");
20. final Label label = new Label();
|
onModuleLoad()方法中,我们需要把生成的显示组件或者组装组建加入到显示页面的对应显示区域。首先,我们需要在页面上使用id属性为显示区域指定唯一的名称(参见清单1中的56行)。com.google.gwt.user.client.ui.RootPanel的静态方法get可以根据传入的字符串参数(参数值就是显示区域的id属性)获取页面上对应的显示区域。
HelloWorld.java的36、37行,就使用了RootPanel的get方法分别获得页面上id为"slot1"、"slot2"的显示区域,然后调用add方法将生成的Button和Label对象加入到显示区域中。
36. RootPanel.get("slot1").add(button);
37. RootPanel.get("slot2").add(label);
|
Ajax最重要的功能就是为用户提供更好的交互体验,GWT中使用和AWT中相同的事件监听机制完成客户端事件监听,GWT中支持的Listener接口包括ChangeListener、ClickListener等。我们可以通过各种各样的Listener接口获得用户界面上所发生的动作,通过处理这些动作来完成对应业务逻辑。
HelloWorld.java中的第22行~29行的内容就实现了一个ClickListender接口,并且提供了对应的onClick方法实现,用于处理按钮点击后的业务逻辑(判断是否需要显示"Hello World!"字符串),然后调用Button对象的addClickListener方法增加监听器。
22. button.addClickListener(new ClickListener() {
23. public void onClick(Widget sender) {
24. if (label.getText().equals(""))
25. label.setText("Hello World!");
26. else
27. label.setText("");
28. }
29. });
|
HelloWorld类的全部源代码内容见清单2。
1. package org.vivianj.gwt.client;
2.
3. import com.google.gwt.core.client.EntryPoint;
4. import com.google.gwt.user.client.ui.Button;
5. import com.google.gwt.user.client.ui.ClickListener;
6. import com.google.gwt.user.client.ui.Label;
7. import com.google.gwt.user.client.ui.RootPanel;
8. import com.google.gwt.user.client.ui.Widget;
9.
10. /**
11. * Entry point classes define <code>onModuleLoad()</code>.
12. */
13. public class HelloWorld implements EntryPoint {
14.
15. /**
16. * This is the entry point method.
17. */
18. public void onModuleLoad() {
19. final Button button = new Button("Click me");
20. final Label label = new Label();
21.
22. button.addClickListener(new ClickListener() {
23. public void onClick(Widget sender) {
24. if (label.getText().equals(""))
25. label.setText("Hello World!");
26. else
27. label.setText("");
28. }
29. });
30.
31. // Assume that the host HTML has elements defined whose
32. // IDs are "slot1", "slot2". In a real app, you probably would not want
33. // to hard-code IDs. Instead, you could, for example, search for all
34. // elements with a particular CSS class and replace them with widgets.
35. //
36. RootPanel.get("slot1").add(button);
37. RootPanel.get("slot2").add(label);
38. }
39. }
|
3. 配置文件HelloWorld.gwt.xml
配置文件中包括两个元素。Inherits元素地设置GWT应用的继承信息,而entry-point元素的class属性则用于设置设置GWT应用的主类。
1. <module> 2. 3. <!-- Inherit the core Web Toolkit stuff. --> 4. <inherits name='com.google.gwt.user.User'/> 5. 6. <!-- Specify the app entry point class. --> 7. <entry-point class='org.vivianj.gwt.client.HelloWorld'/> 8. 9. </module> |
Ajax是当前热门的Web应用开发技术,Java是企业应用开发中的主流技术,GWT框架将这两种技术合二为一,是我们能够应用Java语言来开发Ajax,在保留Ajax技术的优点基础上,解决了Ajax应用开发、调试困难的缺点。
本文中介绍了GWT的基本知识、主要特性,提供了"HelloWorld!"例子说明使用Java和GWT框架开发Ajax应用的开发、编译、测试过程,并且通过对"HelloWorld!"例子中涉及文件的分析,讲解了使用GWT框架开发Ajax应用的技术细节和约束条件。