熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

Hessian 原理分析

2013-11-23 18:56:03  來源: Java核心技術 

  一. 遠程通訊協議的基本原理

  網絡通信需要做的就是將流從一台計算機傳輸到另外一台計算機基於傳輸協議和網絡 IO 來實現其中傳輸協議比較出名的有 http tcp udp 等等 http tcp udp 都是在基於 Socket 概念上為某類應用場景而擴展出的傳輸協議網絡 IO 主要有 bio nio aio 三種方式所有的分布式應用通訊都基於這個原理而實現只是為了應用的易用各種語言通常都會提供一些更為貼近應用易用的應用層協議

  二.應用級協議 BinaryRPC

  BinaryRPC 是一種和 RMI 類似的遠程調用的協議它和 RMI 的不同之處在於它以標准的二進制格式來定義請求的信息 ( 請求的對象方法參數等 ) 這樣的好處是什麼呢就是在跨語言通訊的時候也可以使用

  來看下 Binary RPC 協議的一次遠程通信過程

   客戶端發起請求按照 Binary RPC 協議將請求信息進行填充;

   填充完畢後將二進制格式文件轉化為流通過傳輸協議進行傳輸;

   接收到在接收到流後轉換為二進制格式文件按照 Binary RPC 協議獲取請求的信息並進行處理;

   處理完畢後將結果按照 Binary RPC 協議寫入二進制格式文件中並返回

  問題總結

   傳輸的標准格式是?

  標准格式的二進制文件

   怎麼樣將請求轉化為傳輸的流?

  將二進制格式文件轉化為流

   怎麼接收和處理流?

  通過監聽的端口獲取到請求的流轉化為二進制文件根據協議獲取請求的信息進行處理並將結果寫入 XML 中返回

   傳輸協議是?

  Http

  三.      Hessian ——一種實現遠程通訊的 library

  Hessian 是由 caucho 提供的一個基於 binaryRPC 實現的遠程通訊 library

   是基於什麼協議實現的?

  基於 BinaryRPC 協議實現

   怎麼發起請求?

  需通過 Hessian 本身提供的 API 來發起請求

   怎麼將請求轉化為符合協議的格式的?

  Hessian 通過其自定義的串行化機制將請求信息進行序列化產生二進制流

   使用什麼傳輸協議傳輸?

  Hessian 基於 Http 協議進行傳輸

   響應端基於什麼機制來接收請求?

  響應端根據 Hessian 提供的 API 來接收請求

   怎麼將流還原為傳輸格式的?

  Hessian 根據其私有的串行化機制來將請求信息進行反序列化傳遞給使用者時已是相應的請求信息對象了

   處理完畢後怎麼回應?

  處理完畢後直接返回 hessian 將結果對象進行序列化傳輸至調用端

  四.      Hessian 源碼分析

  以 hessian 和 spring dm server 整合環境為例

       客戶端發起請求

  Hessian 的這個遠程過程調用完全使用動態代理來實現的有客戶端可以看出

  除去 spring 對其的封裝客戶端主要是通過 HessianProxyFactory 的 create 方法就是創建接口的代理類該類實現了接口 JDK 的 proxy 類會自動用 InvocationHandler 的實現類(該類在 Hessian 中表現為 HessianProxy )的 invoke 方法體來填充所生成代理類的方法體

  客戶端系統啟動時

  根據 serviceUrl 和 serviceInterface 創建代理

  HessianProxyFactoryBean 類

  HessianClientInterceptor 類

  createHessianProxy(HessianProxyFactory proxyFactory)

  HessianProxyFactory 類

  public Object create(Class api String urlName)

  客戶端調用 hessian 服務時

  HessianProxy 類的 invoke(Object proxy Method method Object []args) 方法

  String methodName = methodgetName();// 取得方法名

  Object value = args[]; // 取得傳入參數

  conn = sendRequest(mangleName args) ; // 通過該方法和服務器端取得連接

  httpConn = (HttpURLConnection) conn;

  code = (); // 發出請求

  // 等待服務器端返回相應…………

  is = conngetInputStream();

  Object value = inreadObject(methodgetReturnType()); // 取得返回值

  HessianProxy 類的 URLConnection sendRequest(String methodName Object []args) 方法

  URLConnection conn = _factoryopenConnection(_url); // 創建 URLConnection

  OutputStream os = conngetOutputStream();

  AbstractHessianOutput out = _factorygetHessianOutput(os); // 封裝為 hessian 自己的輸入輸出 API

  outcall(methodName args);

  return conn;

       服務器端接收請求並處理請求

  服務器端截獲相應請求交給

  orgspringframeworkremotingcauchoHessianServiceExporter

  具體處理步驟如下

  a) HessianServiceExporter 類

  (HessianExporter) invoke(requestgetInputStream() responsegetOutputStream());

  b) HessianExporter 類

  (HessianSkeletonInvoker) thisskeletonInvokerinvoke(inputStream outputStream);

  c) HessianSkeletonInvoker 類

  將輸入輸出封轉化為轉化為 Hessian 特有的 HessianInput 和 HessianOutput

  HessianInput in = new HessianInput(isToUse);

  insetSerializerFactory(thisserializerFactory);

  AbstractHessianOutput out = null;

  int major = inread();

  int minor = inread();

  out = new HessianOutput(osToUse);

  out = new HessianOutput(osToUse);

  outsetSerializerFactory(thisserializerFactory);

  (HessianSkeleton) thisskeletoninvoke(in out);

  d) HessianSkeleton 類

  讀取方法名

  String methodName = inreadMethod();

  Method method = getMethod(methodName);

  讀取方法參數

  Class []args = methodgetParameterTypes();

  Object []values = new Object[argslength];

  執行相應方法並取得結果

  result = methodinvoke(service values);

  結果寫入到輸出流

  outwriteObject(result);

  總結 由上面源碼分析可知客戶端發起請求和服務器端接收處理請求都是通過 hessian 自己的 API 輸入輸出流都要封裝為 hessian 自己的 HessianInput 和 HessianOutput 接下來一節我們將去了解 hessian 自己封裝的輸入輸出到底做了些什麼!

  五.      Hessian 的序列化和反序列化實現

  hessian 源碼中 comcauchohessianio 這個包是 hessian 實現序列化與反序列化的核心包其中 AbstractSerializerFactory AbstractHessianOutput AbstractSerializer AbstractHessianInput AbstractDeserializer 是 hessian 實現序列化和反序列化的核心結構代碼

   AbstractSerializerFactory 它有 個抽象方法

  根據類來決定用哪種序列化工具類

  abstract public Serializer getSerializer(Class cl) throws HessianProtocolException;

  根據類來決定用哪種反序列化工具類

  abstract public Deserializer getDeserializer(Class cl) throws HessianProtocolException;

   SerializerFactory 繼承 AbstractSerializerFactory

  在 SerializerFactory 有很多靜態 map 用來存放類與序列化和反序列化工具類的映射這樣如果已經用過的序列化工具就可以直接拿出來用不必再重新實例化工具類

  在 SerializerFactory 中實現了抽象類的 getSerializer 方法根據不同的需要被序列化的類來獲得不同的序列化工具一共有 種序列化工具 hessian 為不同的類型的 java 對象實現了不同的序列化工具默認的序列化工具是 JavaSerializer

  在 SerializerFactory 中也實現了抽象類的 getDeserializer 方法根據不同的需要被反序列化的類來獲得不同的反序列化工具默認的反序列化工具類是 JavaDeserializer

   HessianOutput 繼承 AbstractHessianOutput 成為序列化輸出流的一種實現

  它會實現很多方法用來做流輸出

  需要注意的是方法它會先調用 serializerFactory 根據類來獲得 serializer 序列化工具類

  public void writeObject(Object object)

  throws IOException

  {

  if (object == null) {

  writeNull();

  return;

  }

  Serializer serializer;

  serializer = _serializerFactorygetSerializer(objectgetClass());

  serializerwriteObject(object this);

  }

   現在我們來看看 AbstractSerializer

  其 writeObject 是必須在子類實現的方法 AbstractSerializer 有 種子類實現 hessian 根據不同的 java 對象類型來實現了不同的序列化工具類其中默認的是 JavaSerializer

  而 JavaSerializer 的 writeObject 方法的實現遍歷 java 對象的數據成員根據數據成員的類型來獲得各自的 FieldSerializer 一共有 中默認的 FieldSerializer

  拿默認的 FieldSerializer 舉例還是調用 AbstractHessianOutput 的子類來 writeObject 這個時候肯定能找到相應的 Serializer 來做序列化

  同理可以反推出 hessian 的反序列化機制 SerializerFactory 可以根據需要被反序列化的類來獲得反序列化工具類來做反序列化操作

  總結得益於 hessian 序列號和反序列化的實現機制 hessian 序列化的速度很快而且序列化後的字節數也較其他技術少


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25997.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.