使用gwt+cypal studio 进行ajax开发

前言

      最近公司准备要用GWT开发新的项目,而GWT作为Google最近主打的一种新的开发框架,因此,对GWT认真的进行了一番学习和研究.

 

 

GWT和Cypal studio介绍


     GWT是一种利用纯java语言进行动态AJax Web应用开发的完全开源的工具,它无需你特意去编写JavaScript,GWT的编译器会把用于开发客户端的Java代码转化成Javascript和Html,GWT提供了一种宿主模式(Hosted Mode)方便我们的开发和调试,在我们一开始开发的时候就可以设置在Hosted Mode下(后面会详细描述),在这种模式下,JVM会使用GWT内置的浏览器运行编译后的class内容,提供"编码,调试"的最佳速度.
Cypal studio作为GWT开发的Eclipse插件,可以在简化GWT开发的很多任务.目前还在学习中,还未能充分体会其全面的作用,以后会慢慢补充.


GWT和Cypal studio的下载,安装和配置:


     在小生目前的学习阶段,GWT的最新版本为1.5.2,从GWT1.5.0起,GWT已经可以完全的支持JDK1.5,这是GWT相当大的一个飞跃. GWT的官方下载地址:http://code.google.com/webtoolkit/ 下载后解压即可. Cypal studio的下载地址: http://code.google.com/p/cypal-studio/downloads/list .下载完成后,将该文件解压缩到 Eclipse 目录,在功能和插件目录中得到这些文件。然后启动eclipse,访问 Preferences 窗口,如图 1 所示。如果一切运行正常,Cypal Studio 应当在左侧有一个条目。只需将 GWT Home 设置设为先前创建的 GWT 安装的顶级目录。

图 1

 


创建 Cypal Studio 项目

        要使用 Cypal Studio for GWT,必须创建一个新的 Dynamic Web Project 如图 2

图 2


      Configurations 列表中,选择 Default Googlipse Project.然后Finish

 

创建GWT模块

     GWT的基本单位是模块(Module),模块可以说就是一个页面,它一般由一个或多个实现了EntryPoint接口的类组成,这些类在模块被加载的时候被加载,我们选择NEW,GWT Module来创建一个模块,在模块创建成功以后,可以看到在我创建的顶级com.kevin.geng包下,有3个包分别是:public,client,server.在client下可以看到FirstModule.java,这个就是实现了EntryPoint接口的该模块的组成类,也就是模块的入口,或者可以说是页面的入口,public下有FirstModule.html,它通过GWT内置的编译器自动帮你创建.

 

一个例子的创建和运行

     接下来,我讲通过一个简单的猜数字的例子来讲述GWT中的一些基本的组件,事件,以及GWT是如何实现远程服务通信.
     首先,我们在FirstModule.html的body中加入以下代码:

		<table align=center>
			<tr>
				<td id="button"></td>
				<td id="count"></td>
				<td id="sender"></td>
				<td id="response"></td>
			</tr>
		</table>

     该段代码在页面中增加了一个表格,表格第一行中有4个元素.

     然后,我们在FirstModule.java中加入以下代码:

public class FirstModule implements EntryPoint {
	private Button button;
	private Button sender;
	private Label label;
	private Label response;
	int count = 0;
	
	public void onModuleLoad() {
		button = new Button("Count your clicks"); 
		label = new Label(String.valueOf(count));
		sender = new Button("send your count");
		response = new Label("Not guess yet");
		
		button.addClickListener(new ClickListener() {

			public void onClick(Widget arg0) {
				count++;
				label.setText(String.valueOf(count));				
			}			
		});
		
		RootPanel.get("button").add(button);
		RootPanel.get("count").add(label);
		RootPanel.get("sender").add(sender);
		RootPanel.get("response").add(response);
	}
}

     代码位于onModuleLoad()方法中,这个方法会在模块被加载的时候自动被调用,我在这里创建了2个Button和2个Label,在button中增加一个button的点击侦听事件,该事件被触发时,count值会自动加1并同时在label中显示出count值.最后我们通过RootPanel.get("")方法获得获得html中当前的元素,并将我所创建的4个组件的文档对象的DOM ID分别匹配传递给各个元素.

    然后我们先调试下这段程序,Run As > Open Run Dialog , 在Gwt Hosted Mode Application New 一个新的运行配置,选择你当前的module,然后Run ,此时GWT会通过内置的编译器编译你的class,并在内置的浏览器上运行,如图 3:

 

图 3

 

     我们点击"Count your clicks"button,后面label的数字就会自动增加1,这就是GWT中组件以及事件侦听的最基本使用,以及GWT调试的方便性,我们还可以通过Debug模式来运行该Module来进行更深入的调试.

     当然了这仅仅是这个例子的一个开始而已,后面我将通过另一组button和Label的结合来看看GWT中是如何实现Web应用中最重要的核心:远程服务器的通信(Remote Service).

     大家都知道,Web应用的远程调用过程主要在2个类中实现,当然,GWT也不例外,在服务端,通过定义RemoteServiceServlet的子类,操作数据,并将数据返回给客户机;在客户端,通过一个实现了ASyncCallback接口的类来处理返回的数据并完成页面操作.我将继续通过这个例子来详细讲述这个过程:

     首先,我们可以利用Cypal Studio来轻松的创建一个RemoteService,NEW > OTHERS > Cypal Studio > Remote Service ,提示:这里需要定义你的Service的URI.

如图 4所示:

 

图 4

 

    Finish之后,这时你后在client包下发现,Cypal帮你在client包下创建了一个ReomteService接口的子接口NumberGuess.java,这个接口是该远程连接的主接口,而GWT特殊的地方在于,你还需要去定义一个该主接口的异步接口,当客户机调用这些代码的时候,实际上使用的是这个异步接口,而服务端看到的却是被GWT转化后的主接口(据说Cypal Studio会自动帮你创建这个异步接口,不过我目前在使用过程中没有发现此功能,难道是我操作有误?俺还是手动创建算了),ok,不废话了,创建一个NumberGuessAsync接口,然后我们在主接口中加入一个方法getNumber(),代码如下:

public interface NumberGuess extends RemoteService {

	public static final String SERVICE_URI = "numberguess";
	
	public Integer getNumber(int maxNumber);

	public static class Util {

		public static NumberGuessAsync getInstance() {

			NumberGuessAsync instance = (NumberGuessAsync) GWT
					.create(NumberGuess.class);
			ServiceDefTarget target = (ServiceDefTarget) instance;
			target.setServiceEntryPoint(GWT.getModuleBaseURL() + SERVICE_URI);
			return instance;
		}
	}

}

      这里,注意看getInstance()这个方法,这个方式是GWT远程服务的创建和设置,这个方法里每一行都是很重要的,第一行创建了该异步接口的实例,可以看到它是通过主接口来创建;第二行让该实例实现了另一个ServiceDefTarget接口;第三行设置但前远程服务的URL,通过此URL可以得到这个远程服务.

 

      下面这段代码是NumberGuessAsync异步接口(注意:这个接口名一定要是主接口名的后面加上"Async"),可以看见异步接口里这个相同方法的定义和主直接的方法有些不同,它多了一个参数,而且返回值一定要是void, 因为它是使用返回的AsyncCallback 的对象来对服务器的相应执行相应的操作.

 

public interface NumberGuessAsync {
	public void getNumber(int maxNumber,AsyncCallback callback);
}

 

        同时,Cypal studio在service包下创建了一个该接口的实现类,同时也是RemoteServiceServer的子类NumberGuessImpl,该servlet需要你去实现主接口的方法.看下面这段代码:

public class NumberGuessImpl extends RemoteServiceServlet implements NumberGuess {

	public Integer getNumber(int maxNumber) {
		//return a random number form 0 to maxNumber
		return new Integer((int) (Math.random()*maxNumber + 0));
	}
}

    我在这个方法中返回了一个0到maxNumber的随机数给客户机,客户机会通过AsyncCallback的对象来获得.

 

    最后我们到client端,对服务端的响应进行处理.在FirstModule.java中加入相关代码,如下:

public class FirstModule implements EntryPoint {
	private Button button;
	private Button sender;
	private Label label;
	private Label response;
	int count = 0;
	
	public void onModuleLoad() {
		button = new Button("Count your clicks"); 
		label = new Label(String.valueOf(count));
		sender = new Button("send your count");
		response = new Label("Not guess yet");
		
		button.addClickListener(new ClickListener() {
			public void onClick(Widget arg0) {
				count++;
				label.setText(String.valueOf(count));				
			}			
		});
		
		sender.addClickListener(new ClickListener() {
			public void onClick(Widget arg0) {
				NumberGuessAsync async = NumberGuess.Util.getInstance();
				async.getNumber(10, new NumberCallback());
			}
			
		});
		
		RootPanel.get("button").add(button);
		RootPanel.get("count").add(label);
		RootPanel.get("sender").add(sender);
		RootPanel.get("response").add(response);
	}
	
	public class NumberCallback implements AsyncCallback {

		public void onFailure(Throwable error) {
			response.setText("error");
		}

		public void onSuccess(Object back) {
			int backNumber = ((Integer)back).intValue();
			if (backNumber == count) {
				response.setText("Your get it !");	
			}
			if (backNumber > count) {
				response.setText("Too High !");			
			}
			if (backNumber < count) {
				response.setText("Too Low !");			
			}
		}
		
	}
}

     在这个class中,首先给sender这个Button 增加了一个click的侦听事件,注意看该事件的两行代码,第一行GWT获得了当前异步接口的实例,第二行用这个实例触发getNumber()这个方法,然后服务端会执行请求的方法,在服务端完成响应之后,一个实现了AsyncCallback接口的class的对象会被自动调用.最后这个AsyncCallback对象会相应的进行页面处理,在我这个例子中,NumberCallback对象会对响应进行页面处理,AsyncCallback接口定义了2个方法,onFailure() 和 onSuccess(),如果服务器是在异常状况下完成了响应,就会执行onFailure()方法,如果正常响应,就是执行 onSuccess()方法,这个方法中,会接收到服务端返回的Integer对象给back,然后将该返回的结果与count相比较去做相应的页面处理.

     接下来,我们在调试下这个程序,如 图 5:

图 5

 

     成功!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值