1. 程式人生 > >zuul feign微服務間文件上傳

zuul feign微服務間文件上傳

通過 let net 上傳 int @override note into ati

feign傳文件

  • 需求
  1. 文件微服務負責管理文件,具體的文件上傳下載邏輯都在此模塊。
  2. openAPI負責向app用戶提供頭像上傳的接口,實現具體業務邏輯。
  3. zuul是網關,負責路由轉發。用戶直接訪問網關。

頭像文件==》zuul==》openAPI==》文件微服務

  • 增加引用包
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form-spring</artifactId>
            <version>2.1.0</version>
        </dependency>
  • 增加配置類
@Configuration
public class FeignConfiguration {
    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;
    @Bean
    public Retryer retryer(){
        return new Retryer.Default(1000,10000,3);
    }

    @Bean
    Request.Options feignOptions() {
        return new Request.Options(5 * 1000, 10 * 1000);
    }

    // 主要是這個地方
    @Bean
    @Primary
    @Scope("prototype")
    public Encoder multipartFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }

    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    @Bean
    public ErrorDecoder errorDecoder(){
        return new FeignErrorDecoder();
    }

}

異常處理類

public class FeignErrorDecoder implements feign.codec.ErrorDecoder {
    private static final Logger logger = LoggerFactory.getLogger(FeignErrorDecoder.class);

    @Override
    public Exception decode(String methodKey, Response response) {

        if(response.status() >= 400 && response.status() <= 499){
            return new HystrixBadRequestException("微服務之間調用失敗!");
        }

        return feign.FeignException.errorStatus(methodKey, response);
    }

}

在啟動類上加註解@Import(FeignConfiguration.class),導入配置類

@Import(FeignConfiguration.class)

至此可實現feign中文件傳遞

feignclient

 @ApiOperation(value = "用戶修改頭像", notes = "用戶修改頭像")
 @RequestMapping(value = "/v1/user/avatar", method = RequestMethod.PUT)
 public CommonResponse editAvatar(@RequestHeader(value = "openId") String openId,
                                     @RequestPart(value = "file") MultipartFile avatarFile);
  1. RequestPart中的name要和上傳時一致,否則調用失敗。
  2. feign中@RequestHeader傳遞null時,會自動轉為{fileLength},需要手動處理。

zuul

微服務上傳文件成功後,通過zuul網關上傳又出現問題,文件傳不到微服務中。

org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part ‘file‘ is not present

解決方法:
在調用地址前加上/zuul(/zuul/v1/user/avatar),繞過spring mvc,使用zuul servlet去上傳文件。

參考:https://my.oschina.net/kmnztech/blog/1618636

或者在網關的application.properties中設置servlet-path屬性

zuul.servlet-path=/

官方文檔:

http://cloud.spring.io/spring-cloud-static/Dalston.SR1/#_uploading_files_through_zuul

The Zuul Servlet
Zuul is implemented as a Servlet. For the general cases, Zuul is embedded
into the Spring Dispatch mechanism. This allows Spring MVC to be in control
of the routing. In this case, Zuul is configured to buffer requests. If
there is a need to go through Zuul without buffering requests (e.g. for
large file uploads), the Servlet is also installed outside of the Spring
Dispatcher. By default, this is located at /zuul. This path can be changed
with the zuul.servlet-path property.

zuul feign微服務間文件上傳