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

背景

​ Spring Cloud如今已經被愈來愈多的公司採用了,微服務架構比傳統意義上的單服務架構從複雜度上多了不少,出現了不少複雜的場景。好比,咱們的產品是個app,支持第三方登陸功能,在手機端調用第三方受權接口以後,返回了用戶的相關信息,好比open_id,性別,頭像等。這些信息咱們須要保存在咱們服務器上,當時針對頭像是應該保存圖片的url仍是圖片自己發生了歧義,在一番討論以後,得出的結果是,咱們須要經過url將圖片下載到咱們本地,而後調用咱們本身的文件微服務中上傳功能保存起來。java

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

說明

我的博客首發: https://Shiyajian.github.iogithub

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

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

工具

  • 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。api

項目結構

​ 本項目分爲三個角色,分別以下:數組

  • 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來我的,主要就是吹牛侃大山,順便學習技術共同進步。歡迎各類浪的飛起、悶騷到爆的同志來玩,可是不歡迎裝逼的。

相關文章
相關標籤/搜索