使用 GWT 和 RESTful Web 服务构建动态的组织树(5)
 
- UID
- 1066743
|

使用 GWT 和 RESTful Web 服务构建动态的组织树(5)
创建远程服务异步接口远程服务异步接口基于远程服务接口。服务的异步接口必须在相同的包中,名称相同,但是带 “Async” 后缀。每个远程服务方法都有对应的异步方法。但是,异步方法不能有返回类型,它们必须总是返回 void。异步方法不但必须以相同的次序声明相同的参数,而且必须声明另一个泛型 AsyncCallback<T> 参数,其中的 T 是远程服务方法的返回类型。异步方法不抛出异常。清单 9 是示例应用程序的远程服务异步接口。
清单 9. edu.ucar.cisl.gwtRESTTutorialView.client.RESTfulWebServiceProxyAsync1
2
3
4
5
6
7
8
| 1. package edu.ucar.cisl.gwtRESTTutorialView.client;
2. import com.google.gwt.user.client.rpc.AsyncCallback;
3. public interface RESTfulWebServiceProxyAsync {
4. public void invokeGetRESTfulWebService
(String uri, String contentType, AsyncCallback<String> callback);
5. }
|
在服务器上实现代理服务在一个扩展 GWT 类的服务器端类中实现远程服务。在 RESTful Web 服务代理(清单 10)中,这个类实现远程服务 invokeGetRESTfulWebService。这个方法根据 URI 和内容类型构建一个 HTTP 请求并把它发送给 RESTful Web 服务服务器。如果响应码是 200,就缓冲 HTTP 响应中的内容并使用它作为方法的返回值。否则,抛出一个定制的异常。方法捕捉其他异常(比如 MalformedURLException 和 IOException)并抛出定制的异常,让 GWT 客户机可以捕捉到它。
清单 10. edu.ucar.cisl.gwtRESTTutorialView.server.RESTfulWebServiceProxyImpl1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| 1. package edu.ucar.cisl.gwtRESTTutorialView.server;
2. import java.io.BufferedReader;
3. import java.io.IOException;
4. import java.io.InputStream;
5. import java.io.InputStreamReader;
6. import java.net.HttpURLConnection;
7. import java.net.MalformedURLException;
8. import java.net.URL;
9. import com.google.gwt.user.server.rpc.RemoteServiceServlet;
10. import edu.ucar.cisl.gwtRESTTutorialView.client.RESTfulWebServiceProxy;
11. import edu.ucar.cisl.gwtRESTTutorialView.client.RESTfulWebServiceException;
12. public class RESTfulWebServiceProxyImpl extends RemoteServiceServlet
13. implements RESTfulWebServiceProxy {
14. private static final long serialVersionUID = 1L;
15. public RESTfulWebServiceProxyImpl() { // must have
16. }
17. public String invokeGetRESTfulWebService(String uri, String contentType)
18. throws RESTfulWebServiceException {
19. try {
20. URL u = new URL(uri);
21. HttpURLConnection uc = (HttpURLConnection) u.openConnection();
22. uc.setRequestProperty("Content-Type", contentType);
23. uc.setRequestMethod("GET");
24. uc.setDoOutput(false);
25. int status = uc.getResponseCode();
26. if (status != 200)
27. throw (new RESTfulWebServiceException("Invalid HTTP response status
28. code " + status + " from web service server."));
29. InputStream in = uc.getInputStream();
30. BufferedReader d = new BufferedReader(new InputStreamReader(in));
31. String buffer = d.readLine();
32. return buffer;
33. }
34. catch (MalformedURLException e) {
35. throw new RESTfulWebServiceException(e.getMessage(), e);
36. }
37. catch (IOException e) {
38. throw new RESTfulWebServiceException(e.getMessage(), e);
39. }
40. }
41. }
|
实现回调大多数 GWT 书籍和在线教程中的回调示例是用匿名内部类实现的。在本文中,我用真正的类实现回调。这种方法有几个优点。它让代码更加清晰。它允许在运行时把客户机数据与回调类关联起来。回调类的灵活性、可扩展性和代码可重用性更强。例如,可以在回调基类中实现错误处理方法,让所有回调都可以使用它,从而确保以一致的方式处理所有远程服务异常。可以轻松地调试回调类中的代码,而并非所有 IDE 都支持跟踪内部类。
在本文中,我创建一个抽象基类 RestServiceRpcCallback(清单 11)和两个子类 EmployeeRpcCallback(清单 12)和 OrganizationRpcCallback(清单 13)。在清单 11 中,抽象类实现 AsyncCallback 接口。如果服务器请求成功,就调用 onSuccess 方法。否则,调用 onFailure 方法。onFailure 方法显示从服务器传递来的错误消息。onSuccess 方法调用 processResponse 方法处理 RESTful Web 服务服务器返回的字符串。抽象方法 processResponse 由子类实现。抽象基类有一个成员 treeItem,它是 GWT 中 TreeItem 部件的实例,包含客户机数据,在使用回调类时回调与这些数据相关联。根据 TreeItem 部件代表的内容不同,这个类成员将包含存储职员数据或组织数据的应用程序对象。TreeItem 部件用于帮助创建子树和确定弹出窗口的位置。
我创建了一个枚举类型 EventType 和类成员 eventType。这个类成员用于跟踪哪个事件触发了对 RESTful Web 服务服务器的请求,在 RESTful Web 服务服务器返回结果之后,回调需要根据它决定如何处理结果。
清单 11. edu.ucar.cisl.gwtRESTTutorialView.client.callback.RestServiceRpcCallback1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| 1. package edu.ucar.cisl.gwtRESTTutorialView.client.callback;
2. import com.google.gwt.user.client.rpc.AsyncCallback;
3. import com.google.gwt.user.client.ui.TreeItem;
4. import com.google.gwt.user.client.Window;
5. public abstract class RestServiceRpcCallback implements AsyncCallback <String> {
6. TreeItem treeItem;
7. public enum EventType {SELECT_EVENT, STATE_CHANGE_EVENT};
8. protected EventType eventType;
9. public EventType getEventType() {
10. return eventType;
11. }
12. public void setEventType(EventType eventType) {
13. this.eventType = eventType;
14. }
15. public TreeItem getTreeItem() {
16. return treeItem;}
17. public void setTreeItem(TreeItem treeItem) {
18. this.treeItem = treeItem;
19. }
20. public void onSuccess(String result) {
21. if (result == null)
22. return;
23. processResponse(result);
24. }
25. public void onFailure(Throwable caught) {
26. String msg=caught.getMessage();
27. if (msg != null)
28. Window.alert(msg);
29. }
30. protected abstract void processResponse(String response);
31. }
|
|
|
|
|
|
|