Feign源碼學習(3)

  • ReflectiveFeign中看到實現(xiàn)將接口方法解析成Rest請求的核心邏輯在這行代碼:
    //核心邏輯入口紧阔,反射解析目標Class,得到MethodHandler集合
    Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
  • MethodHandler接口的定義為:
  interface MethodHandler {
    Object invoke(Object[] argv) throws Throwable;
  }
  • 只有一個invoke方法剃根,和Proxy的定義類似。
  • 實現(xiàn)Rest請求的實現(xiàn)類為SynchronousMethodHandler狈醉,實現(xiàn)方法為:
  @Override
  public Object invoke(Object[] argv) throws Throwable {
    //根據(jù)輸入?yún)?shù)組裝成HTTP請求模版
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    Retryer retryer = this.retryer.clone();  //重試策略
    while (true) {
      try {
        //執(zhí)行HTTP請求并解析結果,返回
        return executeAndDecode(template);
      } catch (RetryableException e) {
        retryer.continueOrPropagate(e);  //重試策略
        if (logLevel != Logger.Level.NONE) {
          logger.logRetry(metadata.configKey(), logLevel);
        }
        continue;
      }
    }
  }
  • RequestTemplate:封裝REST請求模版惠险,包括HTTP協(xié)議中請求需要的信息。
  • buildTemplateFromArgs.create(argv):輸入?yún)?shù)有可能是HTTP中的Path班巩,Parameter渣慕,HeaderBody等參數(shù)逊桦。每個參數(shù)按順序,代表的意義是在API接口定義時强经,由形參上的標簽(Annotation)決定的睡陪。
  • executeAndDecode(template):執(zhí)行并解析HTTP結果匿情,這個類的核心邏輯:
  Object executeAndDecode(RequestTemplate template) throws Throwable {
    //生成請求實例
    Request request = targetRequest(template);

    if (logLevel != Logger.Level.NONE) {
      logger.logRequest(metadata.configKey(), logLevel, request);
    }

    Response response;
    long start = System.nanoTime();
    try {
      //發(fā)起REST請求,得到響應
      response = client.execute(request, options);
      // ensure the request is set. TODO: remove in Feign 10
      response.toBuilder().request(request).build();
    } catch (IOException e) {
      if (logLevel != Logger.Level.NONE) {
        logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
      }
      throw errorExecuting(request, e);
    }
    long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);

    boolean shouldClose = true;
    try {
      if (logLevel != Logger.Level.NONE) {
        response =
            logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);
        // ensure the request is set. TODO: remove in Feign 10
        response.toBuilder().request(request).build();
      }
      if (Response.class == metadata.returnType()) {
        if (response.body() == null) {
          return response;
        }
        if (response.body().length() == null ||
                response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {
          shouldClose = false;
          return response;
        }
        // Ensure the response body is disconnected
        byte[] bodyData = Util.toByteArray(response.body().asInputStream());
        return response.toBuilder().body(bodyData).build();
      }

      //請求成功的響應處理
      if (response.status() >= 200 && response.status() < 300) {
        if (void.class == metadata.returnType()) {
          return null;
        } else {
          //解析成需要的對象返回
          return decode(response);
        }
      } 
      //404的響應單獨處理
      else if (decode404 && response.status() == 404 && void.class != metadata.returnType()) {
        return decode(response);
      } else {
        //錯誤響應時炬称,轉換為指定的異常對象
        throw errorDecoder.decode(metadata.configKey(), response);
      }
    } catch (IOException e) {
      if (logLevel != Logger.Level.NONE) {
        logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime);
      }
      throw errorReading(request, response, e);
    } finally {
      if (shouldClose) {
        //關閉輸入流
        ensureClosed(response.body());
      }
    }
  }
  • RequestResponseFeignREST請求響應的封裝。
  • client.execute(request, options)HTTP請求實際發(fā)生的步驟转砖,clientHTTP請求客戶端的抽象须鼎,實際使用的HTTP框架是由使用者定義府蔗,支持的包括有:Java原生晋控,OkHttp, ApacheHttpClient等姓赤。
  • return decode(response):成功的響應內(nèi)容轉換成API定義的出參對象。
  • if (decode404 && response.status() == 404 && void.class != metadata.returnType()):在REST規(guī)范中不铆,一般將找不到資源實現(xiàn)為返回404 NOT FOUND錯誤蝌焚。因此404錯誤被認為是一種業(yè)務范疇里的正常響應誓斥,所以Feign404錯誤做了單獨處理只洒。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末劳坑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子距芬,更是在濱河造成了極大的恐慌涝开,老刑警劉巖框仔,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異离斩,居然都是意外死亡银舱,警方通過查閱死者的電腦和手機衷旅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門纵朋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人操软,你說我怎么就攤上這事嘁锯∧粜剑” “怎么了家乘?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵藏澳,是天一觀的道長。 經(jīng)常有香客問我翔悠,道長业崖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任双炕,我火速辦了婚禮,結果婚禮上撮抓,老公的妹妹穿的比我還像新娘。我一直安慰自己丹拯,他們只是感情好站超,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布乖酬。 她就那樣靜靜地躺著死相,像睡著了一般剑刑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上施掏,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音茅糜,去河邊找鬼。 笑死蔑赘,一個胖子當著我的面吹牛狸驳,可吹牛的內(nèi)容都是我干的预明。 我是一名探鬼主播耙箍,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辩昆!你這毒婦竟也來了阅酪?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤术辐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后施无,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡猾骡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年瑞躺,在試婚紗的時候發(fā)現(xiàn)自己被綠了兴想。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡襟企,死狀恐怖嘱么,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情曼振,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布蔚龙,位于F島的核電站,受9級特大地震影響木羹,放射性物質發(fā)生泄漏甲雅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一抛人、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脐瑰,春花似錦妖枚、人聲如沸苍在。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽续誉。三九已至莱没,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饰躲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工井佑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人躬翁。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓焦蘑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盒发。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理宁舰,服務發(fā)現(xiàn)拼卵,斷路器蛮艰,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向對象的用電信息數(shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,952評論 6 13
  • 一說到REST,我想大家的第一反應就是“啊壤蚜,就是那種前后臺通信方式即寡⊥嗨ⅲ”但是在要求詳細講述它所提出的各個約束聪富,以及如...
    時待吾閱讀 3,423評論 0 19
  • 這個營還有1天就要結束了著蟹。假如你是這個群戰(zhàn)略顧問——如果我們將來能一起做點什么事墩蔓,你希望是什么萧豆?————#超級個體...
    Katrina程閱讀 189評論 0 0
  • 小時候家住農(nóng)村,第一次看電影是在1957年的春節(jié)過后炕横,那天正好是正月初八源内,因為是人日子吃面條的第二天所以記得特別清...
    扶青閱讀 826評論 3 7