Spring Cloud下使用Feign Form實現微服務之間的文件上傳

来源:https://www.cnblogs.com/shiyajian/archive/2018/11/25/10017032.html
-Advertisement-
Play Games

背景 ​ Spring Cloud現在已經被越來越多的公司採用了,微服務架構比傳統意義上的單服務架構從複雜度上多了很多,出現了很多複雜的場景。比如,我們的產品是個app,支持第三方登錄功能,在手機端調用第三方授權介面之後,返回了用戶的相關信息,比如open_id,性別,頭像等。這些信息我們需要保存在 ...


背景

​ Spring Cloud現在已經被越來越多的公司採用了,微服務架構比傳統意義上的單服務架構從複雜度上多了很多,出現了很多複雜的場景。比如,我們的產品是個app,支持第三方登錄功能,在手機端調用第三方授權介面之後,返回了用戶的相關信息,比如open_id,性別,頭像等。這些信息我們需要保存在我們伺服器上,當時針對頭像是應該保存圖片的url還是圖片本身發生了歧義,在一番討論之後,得出的結果是,我們需要通過url將圖片下載到我們本地,然後調用我們自己的文件微服務中上傳功能保存起來。

​ 跨服務之間調用,我們採用的是Feign組件,原生的Feign組件並不支持文件上傳,但是如果添加了Feign-Form模塊,那麼就能上傳文件,下麵我通過一篇文章來講述如何通過Feign上傳文件,代碼已經上傳github地址。

說明

個人博客首發: https://Shiyajian.github.io

github項目地址:https://github.com/Shiyajian/examples ,請找spring-cloud/chapter1

本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!

工具

  • IDE :IntelliJ IDEA
  • JDK : jdk 8
  • 構建工具:Gradle 4.10.2
  • Spring Cloud 版本:Finchley.SR2 (截止2018-11-25最新的GA版本,基於boot 2.0.6)
  • Spring Boot 版本:2.0.6.RELEASE (截止2018-11-25最新為2.1.0.RELEASE)

此處採用Gradle而沒有使用Maven作為依賴構建和管理的工具,主要原因是我們公司目前使用的是Gradle,而且從編譯速度,代碼可讀性和清晰度上都遠遠優於Maven。

項目結構

​ 本項目分為三個角色,分別如下:

  • eureka-server : 註冊中心
  • provider-server: 服務提供者,此處模擬一個文件伺服器,提供文件上傳功能
  • consumer-server: 服務消費者,此處模擬一個業務服務,需要調用文件上傳服務

大致的依賴圖如下:

配置並運行

​ 我們首先通過運行感受一下通過Feign上傳文件的流程,在整個項目可以完整運行後,我們再參考文章和代碼一起分析其中設置,並將其應用到自己的應用中

  • 首先clone項目到本地

    git clone https://github.com/Shiyajian/examples.git
  • 安裝並配置Gradle
  • 將項目導入到IDEA中
  • 確認IDEA支持Lombok插件,預設IDEA都支持的,此步驟可忽略
  • 更改IDEA設置,Project Settings(Mac中為Preferences)-> Compiler -> Annoatation Processors -> [√] Enable annotation processing
  • 刷新Gradle,下載依賴並編譯
  • 啟動註冊中心
    • 找到 examples/spring-cloud/eureka-server中的EurekaApplication,運行main方法
    • 打開瀏覽器,運行:http://localhost:8761/,能打開證明成功
  • 啟動Provider項目
    • 找到 examples/spring-cloud/chapter1/provider/provider-service中的ProviderApplication,運行main方法
    • 刷新註冊中心頁面,找到服務證明成功
  • 運行Consumer項目中的測試
    • 打開examples/spring-cloud/chapter1/consumer/consumer-server/src/test目錄
    • 修改com.shiyajian.examples.consumer.service.impl.ConsumerServiceImplTest類中文件的路徑為本機電腦上存在的文件
    • 運行測試方法
    • 方法綠燈結束,在控制台能找到輸出為成功

Provider 服務配置說明

Provider服務為上傳服務的提供者,這裡模擬的是一個文件伺服器,通過上面圖,我們可以看到項目分為2部分,下麵就進行詳細解讀:

  • provider-api

    這個項目最終打成一個可以被引用的jar包,consumer-server通過引用這個jar包可以通過註入方式引用其中的方法,provider-server也需要引用這個jar包,然後實現其中的邏輯,供consumer-server遠程調用。配置api的方法如下:

    • 添加org.springframework.cloud:spring-cloud-starter-openfeign依賴,只需要這一個依賴就夠了,裡面保存Fegin-Form等依賴。

    • 編寫配置類FeignMultipartSupportConfig.java

      public class FeignMultipartSupportConfig {
      
          @Bean
          @Primary
          @Scope("prototype")
          public Encoder multipartFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
              return new FeignSpringFormEncoder(new SpringEncoder(messageConverters));
          }
      
      }
    • 編寫自定義的Encoder,因為這個有個設計得BUG,本身可以解析文件數組,但是代碼缺少對應的判斷,此處參考文章:https://blog.csdn.net/tony_lu229/article/details/73823757,代碼不貼了,詳細見工程

    • 定義自己的介面,這裡我定義的是ProviderClient,代碼簡單如下:

      @FeignClient(value = "provider-server", configuration = FeignMultipartSupportConfig.class)
      public interface ProviderClient { 
      
          @PostMapping(value = "client/upload/{id}", consumes = MULTIPART_FORM_DATA_VALUE)
          String uploadFile(@RequestPart("file") MultipartFile file,
                            @PathVariable("id") String id,
                            @RequestParam("name") String name);
      
          @PostMapping(value = "client/uploads", consumes = MULTIPART_FORM_DATA_VALUE)
          List<ProviderResponse> uploadFiles(@RequestPart("files") MultipartFile[] files, @RequestParam("author") String author);
      
      }

      這個介面定義時候需要有以下註意的幾點:

      • @FeignClient中的value,對應的是服務實現類在eureka中註冊的名字,也就是spring.application.name的值
      • configuration必須配置,就是咱們上面添加的兩個類,用來編解碼使用
      • 方法可以使用類似Controller中的一些註解,比如方法上可以加@RequestMapping,@PostMapping等,類上面不可以加,我試的時候,在class上加了@RequestMapping之後報錯,項目啟動時候顯示Url報錯,其實,也完全不需要加
      • 接受文件的時候,必須是@RequestPart註解,我曾經看有文章說,@RequestPart和@RequestParam通用,但是我自己測試並不是這樣
      • consumes對應請求的contentType,必須為:multipart/form-data,此處使用了靜態導包。
      • 在傳統Controller中,我本身會經常簡寫@RequestParam,忽略他的value欄位。但是Feign介面中不行,如果這些註解沒有括弧中的value那麼就會報錯
      • 不支持@RequestBody註解
    • provider-server

      這個項目是最後實際提供服務的項目,所以必須實現provider-api介面中的方法,並且註冊到eureka服務中。

      • 添加對feign的依賴,添加api項目的依賴,其他依賴略

        compile project(":provider-api")
        "org.springframework.cloud:spring-cloud-starter-feign:$feignVersion"
      • 實現provider-api中ProviderClient介面,生成實現類,並編寫業務代碼,需要註意兩點

        • 因為父級已經在方法上增加了@PostMapping,此處可以省略
        • 如果是通過IDEA快生成的實現類,那麼參數前面的@RequestPart、@RequestParam的註解需要加上,不然報錯
    • consumer-server

      這個項目是消費對方提供服務的項目,需要做的也比較簡單。

      • 添加provider-api的項目依賴,正式環境下,兩個項目可能是不同組開發的,所以需要引入jar包,而不是直接編譯此工程,這裡僅做展示使用

        compile project(":provider-api")
      • 在啟動類上增加註解,掃描添加Feign功能對應的包

        @SpringCloudApplication
        // 這個註解非常重要,不然引用不到client中的方法
        @EnableFeignClients("com.shiyajian.examples.provider")
        public class ConsumerApplication {
            public static void main(String[] args) {
                SpringApplication.run(ConsumerApplication.class);
            }
        }
      • 在需要的地方通過@Autowird方式註入,然後就可以進行調用了

        @Autowired
        ProviderClient providerClient;
        ……
        providerClient.dosomething();
        ……

    總結

    ​ 整個通過Feign-Form上傳文件的案例就寫完了,第一次寫博客,寫的不好還望見諒,如果文章解釋的不夠清楚,可以參考我的項目中的代碼,代碼上可能會更清晰點,代碼我已經測試通過的,可以放心使用。文章中如果有寫錯誤的地方還望各位指正,當然,如果有什麼好的建議也可以給我評論和留言,如果你還其他關於java方面的教程和示例代碼你也可以告訴我,我如果不忙的時候,我就會寫出來。

    意外

    ​ 在發文章之前又做了一次測試,這次測試沒有通過,通過調查發現,Eureka中項目的註冊地址變成了:MacBook-Pro.local:provider-server:8100,然後調用時候就發生url錯誤,請求fe80:0:0:0:***:8100這個地址,等重新聯網之後再次啟動,註冊地址就變成 192.168.1.101這種地址。

      文章發佈在github上沒有問題,在園子裡面出現了格式BUG,調了好長時間沒調好, 就先這樣將就著看吧。猜測原因是小標題後面帶個代碼塊樣式就被頂跑了,但是不知道怎麼處理,剛開始用Markdown,以後再研究吧,見諒見諒。

    其他

    ​ QQ群:757696438是我的個人好友群,目前也就30來個人,主要就是吹牛侃大山,順便學習技術共同進步。歡迎各種浪的飛起、悶騷到爆的同志來玩,但是不歡迎裝逼的。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 帶著問題去閱讀 為什麼說ConcurrentHashMap是線程安全的?或者說 ConcurrentHashMap是如何防止併發的? 2. 欄位和常量 首先,來看一下ConcurrentHashMap中的一些欄位和常量,這些在接下來的操作中會用得到 2.1. 常量 從中,我們可以獲得以下信息: ...
  • a) 一個整型數(An integer) b) 一個指向整型數的指針(A pointer to an integer) c) 一個指向指針的的指針,它指向的指針是指向一個整型數(A pointer to a pointer to an integer) d) 一個有10個整型數的數組(An arra ...
  • 整理了下阿裡近幾年的java面試題目,大家參考下吧,希望對大家有幫助,可以幫大家查漏補缺。 答對以下這些面試題,可以淘汰掉 80 % 的求職競爭者。 1.hashcode相等兩個類一定相等嗎?equals呢?相反呢? 2.介紹一下集合框架? 3.hashmap hastable 底層實現什麼區別?h ...
  • 1.安裝第三方庫(matplotlib,jieba,wordcloud,numpy) 1.1安裝方法:pip命令線上安裝(python3.x預設安裝了pip,pip下載地址:https://pypi.python.org/pypi/pip#downloads) 已經配置好環境變數前提下,在cmd視窗 ...
  • 一、subprocess 註:如果是Windows,那麼res.stdout.read()讀出的是GBK編碼的信息,在接收端需要用GBK解碼且只能從管道里讀一次結果,PIPE稱為管道。 二、粘包現象 1. TCP會粘包,UDP永遠不會粘包 發送端可以是一K一K地發送數據,而接收端的應用程式可以兩K兩 ...
  • 1. 創建一個Maven的項目,我的項目結構如下: 2. 在pom文件里寫下需要導入的依賴: 3. 在Java文件夾下新建package,在package包下新建介面及其實現類 介面: 實現類: 4. 在resources目錄下新建 文件 我們需要在spring容器的配置文件中進行註冊該Bean s ...
  • 一、MyBatis MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。2013年11月遷移到Github。 iBATIS一詞來源於“internet”和“ ...
  • 在上一篇文章中,我們介紹了 Python 的函數式編程,現在我們介紹 Python 的類和繼承。 查看上一篇文章請點擊:https://www.cnblogs.com/dustman/p/10010690.html 類先前,我們研究過兩種編程範式--命令式(使用語句、迴圈和函數)和函數(使用純函數、 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...