龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

基于GWT轻松掌握AJAX开发(1)(2)

时间:2013-03-06 14:58来源:未知 作者:admin 点击:
分享到:
(四)RootPanel Com.google.user.client.ui.RootPanel起到一个从你的Java代码到HTML页面然后再转到浏览器的“window”对象的“导管”的作用。你可以用下列两种方式把G
(四)RootPanel

Com.google.user.client.ui.RootPanel起到一个从你的Java代码到HTML页面然后再转到浏览器的“window”对象的“导管”的作用。你可以用下列两种方式把GWT组件添加到一个浏览器的“window”对象中:

1.使用GWT提供的、基于Java的布局管理器来在你的代码中设计一个完整的用户接口并且把容器实例添加到RootPanel―通过调用RootPanel.get().add(你的容器对象)实现。你的整个接口都是以Java代码形式存在,并且完全是在运行时刻由JavaScript生成。

2.结合HTML与动态的基于代码的接口生成技术。在这一方法中,Web设计者可以继续使用复杂的布局和图形创建Web页面,但是它们必须指定应该由Java代码动态创建的控件的占位符。然后,由你的GWT Java代码(见下面)负责填充这些占位符。

仅使用Java技术构建的UI―例如方法1―比较适合于使用在具有少量的图形、简单的布局以及类似于Google的接口的应用程序情况下;但是对于含有大量的图形和布局的接口情况,你应该考虑使用第二种方法。

你可以把占位符加入到HTML文件中。然后,在Hello.java文件内,使用RootPanel.get(slot name).add(your widget)填充这些占位符:

...






...
Hello.html
...
RootPanel.get("slot1").add(label);
RootPanel.get("slot2").add(button);
...

这种把HTML和代码组合在一起的方法使Web设计者免于创建繁杂的布局和图形,但却同样使Java开发者创建出具有优秀界面的应用程序。

五、用户接口组件―Widget与Panel

就象Java Swing一样,GWT发行中也带有布局管理器和GUI控件,但是它们称为“panel”和“widget”。Widget是用户能够直接与之交互的控件。按钮,例如RadioButton,TextBox,TabBar,Tree和MenuBar等等,都是GWT widget的示例。你可以把这些widget放于一个Panel控件中,然后由它来决定这些widget的位置与布局。HorizontalPanel,VerticalPanel和DockPanel则是GWT的panel的示例。

【注意】Google的GWT参考文档中提供了一个有关panel和widget的完整列表。

这些panel和widget的用法和行为还类似于Java Swing GUI组件。这些组件提供了相应的方法来设置和检索属性,并且支持一个事件监听器模型以处理你的常规键盘和鼠标事件。下列的代码片断是Hello.java类的一部分―这个类负责创建一个简单的GWT按钮,然后重载它并提供一个点击事件监听器:

...

public class Hello implements EntryPoint{

final Button button = new Button("Hello");

...

public void onModuleLoad(){

button.addClickListener(new ClickListener(){

public void onClick(Widget sender) {

...

}

});

}

...

}

尽管widget和panel都相当不错,但是创建复杂的用户接口时往往要求打包,并且要求在这些接口上应用更优秀的可视化效果。要实现这些,就要借助于composite,并结合层叠式样表(CSS)技术。

六、Composite

GWT允许你结合成组的widget和面板来创建新的独立的widget―称作“composite”。下面的列表向你展示了如何把一个按钮和一个面板组合到一起以创建一个具有一定功能的独立的HelloCSS composite:

package com.techyatra.awe.client;

...

public class HelloCSS extends Composite{

final Button buttonCSS = new Button("Apply Style");

final VerticalPanel panel = new VerticalPanel();

public HelloCSS() {

buttonCSS.addClickListener(new ClickListener()

...

buttonCSS.addStyleName("awe-button");

...

);

panel.setHorizontalAlignment(panel.ALIGN_CENTER);

panel.add(buttonCSS);

setWidget(panel);

}

}

这个HelloCSS widget位于根面板中的Hello.java中。事实上,该示例应用程序把逻辑功能封装在了HelloCSS、HelloRPC和HelloHistory三个composite中。

七、层叠式样表(CSS)

GWT的一个极强有力的特征之一就是,它真正广泛地加入了层叠式样表功能。每一个widget和panel都有一个缺省的CSS风格,而且你可以自由地修改之(例如,可以使用“gwt-Button{}”来修改按钮widget)。你还可以使用addStyleName(String)和removeStyleName(String)方法从GWT Java代码中添加和删除你自己的风格。你可以在.css文件内定义这些风格,然后在HTML宿主页面中使用< link > HTML标签引用它们。

下面的列表展示了ajaxwithease.css文件,它包含了本文示例应用程序特定的漂亮的按钮风格―这种风格被应用于在前面的列表中定义的HelloCSS composite中的一个按钮:

...

.gwt-CheckBox {

font-size: smaller;

}

...

.awe-button

{

color:#0000FF;

font-family:'trebuchet ms',helvetica,sans-serif;

font-size:84%;

font-weight:bold;

background-color:#fed;

}

...

这个ajaxwithease.css文件也包括了GWT缺省的风格,因为(令人奇怪的是)applicationCreator.cmd文件并没有创建一个包含GWT缺省风格的.css文件。

现在,既然你已经搭建起客户端(浏览器+HTML/JavaScript)的外观;那么接下来,它需要响应用户事件―通过与一个Web服务器进行通讯来实现数据检索。在过去使用Servlet/JSP开发的日子里,这意味着,每一次到服务器端的迂回都要实现一次完整的页面重载。而使用AJAX技术的最大优点在于,不需要实现这样的整体页面重载,而GWT的RPC机制使得实现这样的服务器通信成为小菜一碟。

八、深入剖析GWT RPC

图3展示了本文中的示例应用程序使用GWT RPC的基本框架结构。

 图3.本文中的示例应用程序使用GWT RPC框架图

下面,让我们详细分析RPC中的每一个组成部分:

远程服务接口―HelloService.java,位于客户端文件夹下,它继承自GWT的RemoteService,用于描述GWT的RPC需要支持的接口。

远程服务实现类―HelloServiceImpl.java,位于服务器文件夹下,实现了在HelloService中定义的远程接口并继承了GWT的RemoteServiceServlet,而RemoteServiceServlet又继承自HttpServlet。事实上,HelloServiceImpl是一个响应于客户端请求(浏览器+HTML/JavaScript)的servlet。该HelloServiceImpl还为模块配置文件hello.gwt.xml所引用―其中,它被映射到“/hello”Servlet路径。

异步回调接口―位于客户端文件夹下的HelloServiceAsync是一个异步回调接口。该类的名字必须是服务接口类的名字,后面跟着“Async”。你不需要实现这个接口,因为它由GWT在后台实现。

【注】GWT的RPC通信的一个“古怪”的方面是,它是异步的。这意味着,当客户端向服务器发出一个调用时,它不必等待服务器立即返回响应。稍后,当服务器端准备好数据后,它就连接回客户端并提供给客户端相应的响应数据。

Serializable类型对象―Person.java是一个可GWT串行化的值对象。它由hello()函数作为一个参数接收。你不需要任何特别的事情来使用该值对象(它们在客户端与服务器端来回传递)。GWT负责处理串行化和反串行化参数并返回原始值和给定的定制Java对象的值。这些定制对象实现了GWT的IsSerialiazable接口,而当你定义这些对象时,只需遵循Google的GWT文档中的一些规则即可。Person对象有些古怪,因为它既在客户端的JavaScript中使用也在服务器端以Java字节代码形式使用。

HelloConstants―这个类不是GWT要求的,但是如果你既想在Eclipse中以GWT宿主方式调试你的应用程序又想在Web服务器(例如Apache Tomcat)中发布你的应用程序的话,那么必须实现它。这个类定义了一个指向Servlet路径的常量―HELLO_SERVICE_URL。当调试应用程序时,你需要使用(去掉注释)相应的代码行―把HELLO_SERVICE_URL设置为/hello,因为这是GWT宿主环境所要求的。然而,当你准备构建一个要发布到一个Web服务器上的WAR文件时,你需要使用(去掉注释)相应的代码行―在运行时刻把HELLO_SERVICE_URL设置为一个等于http://localhost:8080/ajaxwithease-0.1/hello的值以便在一个Web服务器上进行发布。

除了把你的WAR文件发布到一个Web服务器上之外,你还需要把Servlet映射添加到web.xml,如下所示:

...

hello

com.techyatra.awe.server.HelloServiceImpl



hello
/hello

...

HelloRPC―一个消费HelloService服务的复合widget。它首先检索一个相应于HelloService的服务端点,然后把端点入口点设置为HelloServiceImplServlet路径URL。然后,创建一个AsyncCallback的实例,并且把它作为一个参数传递给helloService.hello()函数调用。AsyncCallback实例的onSuccess和onFailure方法被重载以执行示例应用程序特定的处理:

package com.techyatra.awe.client;

...

public class HelloRPC extends Composite {

...

HelloServiceAsync helloService = (HelloServiceAsync)

GWT.create(HelloService.class);

ServiceDefTarget endpoint = (ServiceDefTarget)

helloService;

public HelloRPC() {

endpoint.setServiceEntryPoint

(HelloConstants.HELLO_SERVICE_URL);

...

AsyncCallback callback =new AsyncCallback()

{

public void onSuccess(Object result){

labelRPC.setText((String) result);

}

public void onFailure(Throwable caught){

errorMessage.setHTML(caught.getMessage());

}

};

helloService.hello(

new Person(textTitle.getText(),

textName.getText()), callback);

}

...

}

}

当服务器处理结束并且准备好返回数据时,它使用AsyncCallback来回调客户端,并激活onSuccess()方法。从服务器端抛出的异常被路由到onFailure()方法。

现在,你的应用程序有了漂亮的接口和快速的数据检索能力,但是,程序是否拥有任何历史信息管理功能呢?有了GWT,这也不成问题。

九、优秀的“历史”管理功能

使用基于AJAX的应用程序的一个主要的麻烦在于,它们往往丢失了浏览器back按钮所提供的功能。借助于GWT,历史信息的管理变得非常简单。GWT提供了一个到你的应用程序的钩子(Hook)以响应于浏览器的back和forward事件。

下列的HelloHistory.java列表中展示了一个实现了GWT的HistoryListener接口的HelloHistory复合widget:

package com.techyatra.awe.client;

...

public class HelloHistory extends Composite implements HistoryListener{

public HelloHistory() {

...

History.newItem(textHistory.getText());

...

History.addHistoryListener(this);

}

public void onHistoryChanged(String historyToken) {

String token = History.getToken();

if (token != null){

textHistory.setText(token);

}

}

}

当你的应用程序用户点击他们的浏览器中的“back”和“forward”按钮时,你就有机会在onHistoryChanged()方法中响应它。你可以使用符号(token)来跟踪历史信息,并把符号添加到历史中,然后根据这些符号在onHistoryChanged()函数中执行适当的处理。

十、小结

总之,借助于Google的GWT框架,开发人员能够更快更好地开发基于Web的胖客户端应用程序,而且这样的程序可以不必依赖于广泛使用的Windows操作系统。

(责任编辑:铭铭 mingming_ky@126.com TEL:(010)68476636)


精彩图集

赞助商链接