GWT通信机制初探
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);}public class AddressServiceImpl extends RemoteServiceServlet implements AddressService{private static final long serialVersionUID = 7819604306802209305L; //实现从数据库查询地理信息的数据集@Overridepublic 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;} @Overridepublic void onBeforeRequestDeserialized(String serializedRequest){System.out.println("[INFO] Received Serialized Request Diagram: " + serializedRequest); } @Overridepublic void onAfterResponseSerialized(String serializedResponse) {System.out.println("[INFO] Serialized Response Diagram to be sent: " + serializedResponse);}} /** * 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; }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"); } } }