`
idealab
  • 浏览: 197742 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

GWT通信机制初探

    博客分类:
  • Java
阅读更多
GWT RPC:GWT提供类似Swing的界面开发模式(基于UI组件重用,事件注册及监听等机制),遵循此开发模式的客户端Java代码将被编译为Javascript代码(并优化,压缩),以运行于客户端浏览器中。然而,客户端Java代码不仅仅包含即将呈现在HTML页面中的UI元素,还包含提供服务的接口和相对应的代理接口(实现异步调用服务),服务接口声明即将被
客户端通过RPC调用的方法。服务器端实现该方法来提供具体服务。服务架构参考下图:



服务接口必须继承一个空接口RemoteService:
//提供getAddresses()服务的接口类
import java.util.List;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("address")
public interface AddressService extends RemoteService{
	public List<Address> getAddresses();
}

/*--------------------------------------------------------*/
//代理接口,提供异步调用服务
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;

public interface AddressServiceAsync {
	public void getAddresses(AsyncCallback<List<Address>> callback);
}


服务接口的注释@RemoteServiceRelativePath("address")指定了代理接口调用的服务的相对路径(通常为servlet访问路径);

服务实现类
public class AddressServiceImpl extends RemoteServiceServlet implements AddressService{
	
	private static final long serialVersionUID = 7819604306802209305L;

        //实现从数据库查询地理信息的数据集
	@Override
	public List<Address> getAddresses(){
		List<Address> addr_list = new ArrayList<Address>();
		DBConnectionPool pool = new DBConnectionPool("pool01", "com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/db?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8",
				"admin", "admin123", 5);
		System.out.println("[INFO] Connection Pool created!");
		ResultSet rs = null;
		String sqlStmt = "SELECT addr_id,state,city,address,zip,description FROM address";
		try {
			Connection conn = pool.getConnection();
			System.out.println("[INFO] Connection to DB established!");
			PreparedStatement ps = conn.prepareStatement(sqlStmt);
			rs = ps.executeQuery();
			if(rs == null){
				System.out.println("[ERROR] Failed to query data from database!");
				return null;	
			}
			System.out.println("[INFO] Execution of query for address list finished!");
			Address addr = null;
			int cnt = 0;
			while(rs.next()){
				addr = new Address();
				++cnt;
				System.out.println("[INFO] No. " + cnt + " of the result records.");
				addr.setId(rs.getLong("addr_id"));
				addr.setState(rs.getString("state") == null ? "N/A" : rs.getString("state"));
				addr.setCity(rs.getString("city"));
				addr.setAddress(rs.getString("address"));
				addr.setZip(rs.getString("zip"));
				addr.setDescription(rs.getString("description") == null ? "N/A" : rs.getString("description") );
				addr_list.add(addr);
			}
		} catch (SQLException e) {
			System.out.println("[ERROR] Failed to get field value from resultSet!");
			e.printStackTrace();
		}
		return addr_list;
	}

        @Override
	public void onBeforeRequestDeserialized(String serializedRequest){
		System.out.println("[INFO] Received Serialized Request Diagram: " + serializedRequest);
        }

        @Override
	public void onAfterResponseSerialized(String serializedResponse) {
		System.out.println("[INFO] Serialized Response Diagram to be sent: " + serializedResponse);
	}
}


实现类所继承的RemoteServiceServlet是GWT提供的核心Servlet处理类,该类接收客户请求,反序列化RPC请求数据包(GWT提供了序列化及反序列化类库),将反序列化之后的数据交由开发者做业务处理,处理结果将被序列化并组织为响应对象返回客户端。以下为该Servlet处理类的对请求的处理过程:
 /**
   * Standard HttpServlet method: handle the POST.
   * 
   * This doPost method swallows ALL exceptions, logs them in the
   * ServletContext, and returns a GENERIC_FAILURE_MSG response with status code
   * 500.
   * 
   * @throws ServletException
   * @throws SerializationException
   */
  @Override
  public final void processPost(HttpServletRequest request,
      HttpServletResponse response) throws IOException, ServletException,
      SerializationException {
    // Read the request fully.
    String requestPayload = readContent(request);

    // Let subclasses see the serialized request.
    onBeforeRequestDeserialized(requestPayload);

    // Invoke the core dispatching logic, which returns the serialized
    // result.
    String responsePayload = processCall(requestPayload);

    // Let subclasses see the serialized response.
    onAfterResponseSerialized(responsePayload);

    // Write the response.
    writeResponse(request, response, responsePayload);
  }

  //本方法处理反序列化后的请求数据
  public String processCall(String payload) throws SerializationException {
    try {
      RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass(), this);
      onAfterRequestDeserialized(rpcRequest);
      return RPC.invokeAndEncodeResponse(this, rpcRequest.getMethod(),
          rpcRequest.getParameters(), rpcRequest.getSerializationPolicy(),
          rpcRequest.getFlags());
    } catch (IncompatibleRemoteServiceException ex) {
      log(
          "An IncompatibleRemoteServiceException was thrown while processing this call.",
          ex);
      return RPC.encodeResponseForFailure(null, ex);
    }
  }

/*---------------------- RPC.java -------------------------*/
//RPC类中定义的方法invokeAndEncodeResponse,采用反射机制来调用具体的服务方法。
  public static String invokeAndEncodeResponse(Object target,
      Method serviceMethod, Object[] args,
      SerializationPolicy serializationPolicy, int flags)
      throws SerializationException {
    if (serviceMethod == null) {
      throw new NullPointerException("serviceMethod");
    }

    if (serializationPolicy == null) {
      throw new NullPointerException("serializationPolicy");
    }

    String responsePayload;
    try {
      Object result = serviceMethod.invoke(target, args);

      responsePayload = encodeResponseForSuccess(serviceMethod, result,
          serializationPolicy, flags);
    } catch (IllegalAccessException e) {
      SecurityException securityException = new SecurityException(
          formatIllegalAccessErrorMessage(target, serviceMethod));
      securityException.initCause(e);
      throw securityException;
    } catch (IllegalArgumentException e) {
      SecurityException securityException = new SecurityException(
          formatIllegalArgumentErrorMessage(target, serviceMethod, args));
      securityException.initCause(e);
      throw securityException;
    } catch (InvocationTargetException e) {
      // Try to encode the caught exception
      //
      Throwable cause = e.getCause();

      responsePayload = encodeResponseForFailure(serviceMethod, cause,
          serializationPolicy, flags);
    }

    return responsePayload;
  }


onBeforeRequestDeserialized()和onAfterResponseSerialized()由实现类继承,以做定制化处理。

以下是从客户端获取的请求数据包及请求属性:
引用

[INFO]  Received Serialized Request Diagram: 5|0|4|http://localhost:1947/gmap/|A16261BA4B0DD6867308FEA211E4BEC2|com.wipro.gmap.client.AddressService|getAddresses|1|2|3|4|0|
[INFO]  ContentType: text/x-gwt-rpc; charset=utf-8 ServletPath: /gmap/address ContextPath: Protocol: HTTP/1.1 Remote Address: 127.0.0.1 Remote Host: 127.0.0.1:1949 Remote User: null

[Header Information]:
[Host]: localhost:1947 [Connection]: keep-alive [User-Agent]: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Chrome/4.0.222.5 Safari/532.2 [Referer]: http://localhost:1947/gmap/hosted.html?gmap [Accept]: */* [Accept-Encoding]: gzip,deflate [Accept-Language]: en-US,en;q=0.8 [Accept-Charset]: UTF-8,*;q=0.5 [Content-Length]: 127 [Origin]: http://localhost:1947 [X-GWT-Module-Base]: http://localhost:1947/gmap/ [Content-Type]: text/x-gwt-rpc; charset=utf-8 [X-GWT-Permutation]: HostedMode



以下为处理后即将返回客户端的数据包(JSON数据格式):
引用

[INFO]  Serialized Response Diagrm to be sent: //OK[7,13,0.0,3.0,5,12,11,2,7,10,0.0,2.0,5,9,8,2,7,6,0.0,1.0,5,4,3,2,3,1,["java.util.ArrayList/3821976829","com.wipro.gmap.client.Address/1028263900","Golden Gate Bridge","San Francisco","","california","611756","Main St","Oxford","New York","Zhonghe","Chengdu","Sichuan"],0,5]


该数据返回客户端后将触发回调方法,回调方法定义在入口类(EntryPoint)中:
//final ArrayList<Address> addressList = new ArrayList<Address>();
//final ListBox addresses = new ListBox();

AddressServiceAsync as = (AddressServiceAsync) GWT
				.create(AddressService.class);
as.getAddresses(new AsyncCallback<List<Address>>() {
	@Override
	public void onSuccess(List<Address> result) {
		Window.alert("[INFO] Succeed to retrieve data from db!");
		Iterator<Address> it = result.iterator();
		Address address = null;
		while(it.hasNext()){
			address = new Address();
			address = it.next();
			System.out.println("[INFO] Address: " + address.getAddress());
			addresses.addItem(address.getAddress());
			addressList.add(address);
		}
		System.out.println("[INFO] Data in addresses ListBox:");
		addresses.setVisibleItemCount(result.size());
		addressGrid.setAddress(addressList.get(0));
		System.out.println("[INFO] [GMap.getAddresse()] Retrieved addresses already be populated into the ListBox!");
	}

	@Override
	public void onFailure(Throwable caught) {
	        String msg = "[ERROR] Failed to retrieve data from database!";
            	Window.alert(msg);
        	System.out.println(msg);
	        GWT.log(msg, caught);
        }
});


服务接口及相应的异步接口由GWT编译至客户端Javascript中,由GWT Plugin根据服务器地址及端口,模块(Module),服务调用的页面来对服务器进行RPC调用。参考编译后的客户端JS代码(GWT Plugin负责连接服务器,调用服务端RPC服务):
if (!plugin) {
    // try searching for a v1 plugin for backwards compatibility
    var found = false;
    for (var i = 0; i < pluginFinders.length; ++i) {
      try {
        plugin = pluginFinders[i]();
        if (plugin != null && plugin.connect($hosted, $moduleName, window)) {
          return;
        }
      } catch (e) {
      }
    }
    loadIframe("http://gwt.google.com/missing-plugin");
  } else {
    if (plugin.connect(url, topWin.__gwt_SessionID, $hosted, $moduleName,
        $hostedHtmlVersion)) {
      window.onUnload = function() {
        try {
          // wrap in try/catch since plugins are not required to supply this
          plugin.disconnect();
        } catch (e) {
        }
      };
    } else {
      if (errFn) {
        errFn(modName);
      } else {
        alert("Plugin failed to connect to hosted mode server at " + $hosted);
        loadIframe("http://code.google.com/p/google-web-toolkit/wiki/TroubleshootingOOPHM");
      }
    }
  }
  • 大小: 19 KB
1
0
分享到:
评论
2 楼 tinger1 2016-07-07  
狂赞楼主! 
1 楼 wwt18946637566 2015-03-31  
这样的文章要顶一个,讲的真明白

相关推荐

    GWT学习经验及实例指导

    通过实例学习GWT,你可以逐步理解如何创建用户界面,处理事件,与服务器进行异步通信,以及如何利用GWT的其他高级特性,如国际化、模块化和性能优化。 总之,GWT为Java开发者提供了一个强大的工具集,使得构建动态...

    GWT入门 GWT中文教程

    “GWT入门”和“GWT中文教程”显然是针对初学者的,它们可能从最基础的GWT安装、项目配置开始,逐步讲解GWT的核心概念,如UI设计(Widget系统)、事件处理、数据模型和服务器通信(RPC机制)、本地存储、国际化等。...

    gwt 练习 gwt学习

    6. **RPC通信**:GWT的Remote Procedure Call (RPC)机制使得客户端和服务器之间能进行数据交换。在StockWatcher中,可能需要一个服务接口来获取实时股票数据。 7. **异步编程**:由于RPC调用是异步的,开发者需要...

    GWT快速开发(GWT) 是一个Java软件开发框架用于开发类似于Google Maps和Gmail的AJAX应用程序。GWT的设计参考Java AWT包设计,类命名规则、接口设计、事件监听等。你可以用Java编程语言开发你的界面,然后用GWT编译器将Java类转换成适合浏览器执行的...

    - GWT支持通过远程过程调用(Remote Procedure Call, RPC)机制与服务器端进行通信。 - 开发者可以通过定义服务接口并实现相应的服务端逻辑,实现前后端的数据交换。 #### 四、GWT实战案例 - **案例1: Hello GWT...

    GWT操作数据库例子

    GWT提供了丰富的UI组件库,如表格、按钮、输入框等,以及异步通信机制,使得Web应用能够与服务器进行高效的交互。在这个例子中,GWT可能被用来创建一个用户界面,展示从数据库检索的数据。 描述 "用表格显示在页面...

    GWT简介.docx

    5. **异步通信(Ajax)**:GWT内置了异步通信机制,通过GWT的RequestBuilder或GWT-RPC(Remote Procedure Call)实现与服务器的无缝交互,实现页面的无刷新更新。 6. **本地化支持**:GWT支持多语言环境,开发者...

    GWT

    5. **异步通信**:GWT支持异步的服务器通信(Asynchronous JavaScript and XML,AJAX),使得用户界面更加响应式,提高了用户体验。 6. **可访问性**:GWT提供了对Web标准的支持,如WAI-ARIA,帮助创建可访问性和...

    smartgwt最新版本GWT的DEMO

    5. **异步通信**:GWT的RPC机制使得客户端和服务器之间的通信变得简单,DEMO会展示如何使用ServiceDefTarget和AsyncCallback进行异步请求。 6. **性能优化**:SmartGWT通过延迟加载、分块加载等策略提高了组件加载...

    GWT开发环境JAVA

    2. **异步RPC**:GWT提供了基于HTTP的远程过程调用(RPC)机制,使得客户端和服务器之间的通信变得简单高效。 3. **本地存储**:GWT支持在浏览器中进行本地数据存储,即使在网络断开时也能保持应用状态。 4. **...

    GWT Demo,GWT学习时的一些小例子

    3. **异步通信 (RPC)**:GWT 支持异步远程过程调用(RPC),使得客户端与服务器之间的通信变得简单而高效。通过XMLHttpRequest,客户端可以发送异步请求到服务器,处理结果后更新UI,提供流畅的用户体验。 4. **...

    gwt揭秘源代码

    通过《GWT 揭秘》的源代码,读者可以学习到如何创建GWT项目,设置模块,使用GWT的UI组件,实现异步通信,以及优化和调试代码。此外,书中可能还涵盖了自定义Widget、国际化、CSS样式控制、单元测试等方面的内容。 ...

    GWT入门和进阶

    GWT提供了丰富的事件处理机制,如按钮点击、鼠标移动等,你可以通过`addClickListener`等方法来绑定事件处理器。 **4. 数据绑定与Model-View-Presenter模式** GWT支持数据绑定,使得UI组件的状态能自动与后台模型...

    Gwt中文手册,GWt入门

    Gwt中文手册,GWt入门Gwt中文手册,GWt入门Gwt中文手册,GWt入门

    GWT入门与经典实例解析

    3. **客户端-服务器通信**:GWT提供异步RPC(Remote Procedure Call)机制,使得客户端和服务器之间的通信变得简单且高效。 4. **UI组件**:GWT包含一套完整的用户界面组件库,如按钮、文本框、表格等,方便构建...

Global site tag (gtag.js) - Google Analytics