添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
io.github.openfeign.form feign-form 3.8.0 io.github.openfeign.form feign-form-spring 3.8.0

编写Feign Client

* @author hushow * @Descrption * @date 2022/03/23 10:25 @FeignClient(name = "${hushow.feign.service-name:ability-service}", contextId = "ability-lfile", configuration = StorageLocalFeignService.FeignUploadConfig.class) public interface StorageLocalFeignService { class FeignUploadConfig { @Bean public Encoder springEncoder(ObjectFactory<HttpMessageConverters> messageConverters) { return new SpringFormEncoder(new SpringEncoder(messageConverters)); @Bean Request.Options feignOptions() { return new Request.Options(2000, TimeUnit.SECONDS, -1, TimeUnit.SECONDS, true); * 文件上传 * hushowly * @param bucketName * @param file * @param fileName * @param relativeUrl * @param isPrivate * @return @PostMapping(value = "/ability/v1/lfile/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) Result<StorageFileResp> uploadFile(@RequestParam(value = "bucketName", required = true) String bucketName, @RequestPart(value = "file", required = true) MultipartFile file, @RequestParam(value = "fileName", required = true) String fileName, @RequestParam(value = "relativeUrl", required = false) String relativeUrl, @RequestParam(value = "isPrivate", required = false) Boolean isPrivate);

客户端调用

StreamMultipartFile streamMultipartFile = new StreamMultipartFile(key, fileName, inputStream, fileSize, mimeTypeStr);
Result<StorageFileResp> response = storageLocalFeignService.uploadFile(bucketName, streamMultipartFile, fileName, key, isPrivate);

上传和下载时超时的坑

第一步,FeignUploadConfig配置超时

@Bean
Request.Options feignOptions() {
return new Request.Options(2000, TimeUnit.SECONDS, -1, TimeUnit.SECONDS, true);

结果发现不起作用,调试源码后发现,配置文件中feign超时配置优先级高,通过单独配置上传feign解决问是:

feign:
client:
    config:
        default:
            loggerLevel: FULL
            connectTimeout: 2000
            readTimeout: 2000
        ability-lfile:
            loggerLevel: FULL
            connectTimeout: 2000
            readTimeout: -1

feign超时配置逻辑源码位置(FeignClientFactoryBean类)

protected void configureFeign(FeignContext context, Feign.Builder builder) {
    FeignClientProperties properties = this.applicationContext
            .getBean(FeignClientProperties.class);
    if (properties != null) {
        if (properties.isDefaultToProperties()) {
             # 读取类加载的时候认配置
            configureUsingConfiguration(context, builder);
             # 如果存在使用属性文件中默认配置,则覆盖
            configureUsingProperties(
                    properties.getConfig().get(properties.getDefaultConfig()),
                    builder);
             # 如果存在属性文件特定上contextId配置则覆盖配置
            configureUsingProperties(properties.getConfig().get(this.contextId),
                    builder);
        else {
            configureUsingProperties(
                    properties.getConfig().get(properties.getDefaultConfig()),
                    builder);
            configureUsingProperties(properties.getConfig().get(this.contextId),
                    builder);
            configureUsingConfiguration(context, builder);
    else {
        configureUsingConfiguration(context, builder);

尝试上传大文件后,出现OOM坑

经分析,feign暂时不支持大文件,github有人上报,至今未修复

https://github.com/OpenFeign/feign-form/issues/101

分析源码后,发现竟读取字节数组到内存中! 本打算自己理写实现,发现feign上层根本未考虑Stream方式设计,所以暂时未打通feign上传方案,使restTemplate方案进行了代替

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
    at java.io.OutputStream.write(OutputStream.java:75)
    at feign.form.multipart.Output.write(Output.java:65)
    at feign.form.multipart.Output.write(Output.java:53)
    at feign.form.multipart.AbstractWriter.write(AbstractWriter.java:37)
    at feign.form.MultipartFormContentProcessor.process(MultipartFormContentProcessor.java:87)
    at feign.form.FormEncoder.encode(FormEncoder.java:105)
    at feign.form.spring.SpringFormEncoder.encode(SpringFormEncoder.java:84)