`

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开发者手册 GWT

    - **编译原理**:GWT的核心在于其编译器,能够将Java代码转换为等效的JavaScript代码。这一过程使得开发者能够在客户端实现复杂的逻辑处理,同时保持代码的可读性和可维护性。 - **调试支持**:手册提到了GWT支持在...

    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组件和皮肤,尤其是桌面...

    GWT开发者手册 GWT开发者手册

    - **序列化**:GWT不支持标准JAVA序列化,但提供了RPC机制,实现远程方法调用时的对象自动序列化。 **跨浏览器支持** GWT设计为跨浏览器兼容,允许在单一代码基础上支持多种浏览器,减少了处理浏览器兼容性问题的...

    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. 其他高级功能

Global site tag (gtag.js) - Google Analytics