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来我的,主要就是吹牛侃大山,顺便学习技术共同进步。欢迎各类浪的飞起、闷骚到爆的同志来玩,可是不欢迎装逼的。

相关文章
相关标签/搜索