`

GWT RPC原理浅析(二)

    博客分类:
  • OPEN
阅读更多
前一篇介绍了RPC大体的流程,核心方法是RemoteServiceServlet类中的processPost方法

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);
  }


这是一个final方法,无法覆写。不过GWT为我们提供了前置后置方法,供我们覆写:
onBeforeRequestDeserialized 请求反序列化之前的处理
onAfterResponseSerialized 响应序列化之后的处理

下面我们深入这三个步骤
1. readContent(request)
这里调用了内部的一个方法
protected String readContent(HttpServletRequest request)
      throws ServletException, IOException {
    return RPCServletUtils.readContentAsGwtRpc(request);
  }

解析的工作由RPCServletUtils来处理,进入此方法

public static String readContentAsGwtRpc(HttpServletRequest request)
      throws IOException, ServletException {
      return readContent(request, GWT_RPC_CONTENT_TYPE, CHARSET_UTF8);
  }

调用了同名方法,添加了2个参数,分别是请求格式(text/x-gwt-rpc) 编码(utf-8)
进入

public static String readContent(HttpServletRequest request,
      String expectedContentType, String expectedCharSet)
      throws IOException, ServletException {
    if (expectedContentType != null) {
      checkContentTypeIgnoreCase(request, expectedContentType);
    }
    if (expectedCharSet != null) {
      checkCharacterEncodingIgnoreCase(request, expectedCharSet);
    }

    /*
     * Need to support 'Transfer-Encoding: chunked', so do not rely on
     * presence of a 'Content-Length' request header.
     */
    InputStream in = request.getInputStream();
    byte[] buffer = new byte[BUFFER_SIZE];
    ByteArrayOutputStream out = new  ByteArrayOutputStream(BUFFER_SIZE);
    try {
      while (true) {
        int byteCount = in.read(buffer);
        if (byteCount == -1) {
          break;
        }
        out.write(buffer, 0, byteCount);
      }
      String contentCharSet = expectedCharSet != null
          ? expectedCharSet : CHARSET_UTF8;
      return out.toString(contentCharSet);
    } finally {
      if (in != null) {
        in.close();
      }
    }
  }


此处拿到request的输入流,并将内容转换为String类型返回。
至此readContent结束。
2. processCall(String payload)
处理这个请求的RPC调用

public String processCall(String payload) throws SerializationException {
    // First, check for possible XSRF situation
    checkPermutationStrongName();

    try {
      RPCRequest rpcRequest = RPC.decodeRequest(payload, delegate.getClass(), this);
      onAfterRequestDeserialized(rpcRequest);
      return RPC.invokeAndEncodeResponse(delegate, 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.decodeRequest()方法对提交上来的文本解析,生成一个RPCRequest对象
进入此方法

public static RPCRequest decodeRequest(String encodedRequest, Class<?> type,
      SerializationPolicyProvider serializationPolicyProvider) {
   
	//….. 省略部分代码
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

    try {
      ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
          classLoader, serializationPolicyProvider);
      streamReader.prepareToRead(encodedRequest);

     //省略大量代码
//此处通过序列化读入流,解析文本,得出请求中需要调用的类名,方法名,已经方法签名数据 根据这些参数创建RPCRequest对象返回

        return new RPCRequest(method, parameterValues, serializationPolicy,
            streamReader.getFlags());

      } catch (NoSuchMethodException e) {
        throw new IncompatibleRemoteServiceException(
            formatMethodNotFoundErrorMessage(serviceIntf, serviceMethodName,
                parameterTypes));
      }
    } catch (SerializationException ex) {
      throw new IncompatibleRemoteServiceException(ex.getMessage(), ex);
    }
  }

获得了RPCRequest对象后,通过RPC.invokeAndEncodeResponse()调用业务对象完成RPC

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;
  }

拿到需要返回的序列化结果后,将其写入response
3. writeResponse
private void writeResponse(HttpServletRequest request,
      HttpServletResponse response, String responsePayload) throws IOException {
    boolean gzipEncode = RPCServletUtils.acceptsGzipEncoding(request)
        && shouldCompressResponse(request, response, responsePayload);

    RPCServletUtils.writeResponse(getServletContext(), response,
        responsePayload, gzipEncode);
  }


在写入response时,还判断浏览器是否支持gzip压缩,如果支持,则调用RPCServletUtils.writeResponse方法时,传参gzipEncod=true
当然内容还会判断,如果响应内容长度小于255,还是不会压缩的。

至此RPC整个请求响应完成

分享到:
评论

相关推荐

    GWT RPC详细例子:代码加文档说明

    压缩包中的“GWTRPC”可能是一个包含示例代码的文件或目录,它可能包括服务接口、服务实现、服务代理以及必要的测试类。这些代码可以让你更好地理解如何实际操作GWT RPC。同时,“说明文档.doc”提供了详细的步骤和...

    基于GWTRPC的通讯软件

    6. **学习与实践**:理解GWTRPC的工作原理并掌握其应用,对于开发高效的Web应用程序至关重要。开发者需要熟悉Java和JavaScript,了解HTTP协议,以及JSON序列化和反序列化的概念。同时,阅读和分析"基于GWTRPC的通讯...

    spring-gwtrpc:GWT RPC服务的Spring集成

    介绍gwtrpc-spring项目限制了Spring GWT-RPC。 其目的是提供后者的简化和更新版本。得到它Spring GWT-RPC在Maven Central上发布: &lt; dependency&gt; &lt; groupId&gt;fr.sertelon.spring&lt;/ groupId&gt; &lt; artifactId&gt;spring-gwt...

    GWT-RPC-1.pdf

    根据给定文件的信息,我们可以深入探讨GWT-RPC(Google Web Toolkit Remote Procedure Call)的核心概念、开发流程以及在不同模式下的测试方法。 ### GWT-RPC:大想法 GWT-RPC提供了一种机制,允许客户端...

    GWT-RPC.pdf

    根据提供的文件信息,我们可以深入探讨GWT-RPC的相关知识点,主要围绕其概念、开发流程以及部署等几个方面展开。 ### GWT-RPC:基础知识与概念 #### RPC:远程过程调用 RPC(Remote Procedure Call)是一种协议,...

    GWT-RPC-2.pdf

    根据给定文件的信息,我们可以深入探讨GWT-RPC(Google Web Toolkit Remote Procedure Call)的高级特性,特别是关于处理多线程、部署以及异步方法的处理。这些知识点对于理解和运用GWT-RPC进行高效Web应用开发至关...

    Gwt连接数据库的案例

    通过这个案例,你可以学习如何将GWT应用与数据库集成,理解GWT RPC的工作原理,以及如何安全有效地进行数据库操作。这将有助于你构建更复杂的GWT应用程序,提供丰富的用户体验并确保数据的安全交互。

    gwt 练习 gwt学习

    在学习GWT的过程中,练习StockWatcher可以帮助你掌握GWT的核心组件和工作原理。逐步理解并实践这些知识点,你将能够创建更复杂、功能丰富的GWT应用程序。记得在实践中不断尝试、调试和优化,以加深对GWT的理解。

    GWT学习经验及实例指导

    【GWT 概述】 Google Web Toolkit(GWT)是一个开放源码的开发框架,它允许Java开发人员使用Java语言创建复杂的Ajax应用程序。GWT利用Java的强类型和丰富的库来简化Web应用的开发,同时克服了Ajax开发中的挑战,如...

    GWT入门 GWT中文教程

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

    gwt-rpc-serialization:重用 gwt-storage 和 gwt-rpc 序列化技术在客户端序列化对象的概念证明

    GWT-RPC使用高效的二进制编码,这使得数据传输更快速且节省带宽。在GWT-RPC中,开发者定义服务接口和服务实现,GWT编译器会自动生成对应的JavaScript代码,处理这些远程调用的细节。 **GWT-Storage序列化** GWT-...

    GWT中的xmlHttpRequest

    GWT还提供了更高级的RPC(Remote Procedure Call)机制,使得Java对象能够在客户端和服务器之间直接传递。虽然RPC不是基于XMLHttpRequest,但它们底层都依赖于类似的HTTP请求。通过定义服务接口和服务端点,GWT会...

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

    无论是对于初学者还是有经验的开发者来说,掌握GWT的基本原理和开发流程都是非常有价值的。随着技术的不断进步,虽然GWT可能不再是当前最流行的前端开发框架之一,但它仍然在某些特定场景下发挥着重要作用。

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

    通过研究这些示例,开发者可以更好地理解GWT的工作原理和最佳实践。 例如,一个示例可能展示了如何创建一个按钮控件,当用户点击按钮时,通过GWT的RPC机制向服务器发送请求,获取数据并更新页面上的显示。另一个...

    Gwt开发文档

    5. **异步通信(GWT RPC)**: GWT提供了Remote Procedure Call (RPC)机制,使得客户端和服务器之间的数据交换变得简单。开发者可以通过定义服务接口和服务实现,方便地进行异步调用。 6. **GWT Gin**: Gin是一个依赖...

    GWT打包学习资料

    GWT提供了丰富的UI组件库、强大的调试工具以及对异步RPC(Remote Procedure Call)的支持,使得开发复杂的Web应用变得更加便捷。 **GXT (Ext GWT)** 是基于GWT的一个扩展库,提供了更多的UI组件和皮肤,尤其是桌面...

    Google Web工具包(GWT)编程手册The Google Web Toolkit (GWT) Programming Cookbook

    例如,询问GWT是什么、模块描述符的作用、GWT模块和入口点类的定义、如何启用断言、GWT小部件的默认样式、国际化、GWT RPC的使用、浏览器定向编译、同源策略在GWT中的影响、如何创建自定义小部件、 UiBinder的作用...

    GWT揭秘(书签整理版)

    115提供的那个不知道怎么回事,我一直下不下来,后来在论坛...8. GWT-RPC 9. Ext GWT 10. (实战)俄罗斯方块游戏 11. (实战)费用申请审批流程 12. GWT与Flex整合 13. 图片缓存 CSS Sprite 14. 本地化 15. 其他高级功能

    GWT通信机制初探

    1. GWT RPC的工作原理,包括HTTP请求、JSON序列化和异步回调。 2. 如何定义和使用GWT服务接口,以及服务端的实现。 3. 数据对象的序列化与反序列化过程。 4. GWT开发工具的使用,如开发模式和编译器。 5. GXT组件库...

Global site tag (gtag.js) - Google Analytics