【问题标题】:Feign multipart with Json request part使用 Json 请求部分假装多部分
【发布时间】:2020-11-14 03:31:17
【问题描述】:

我在一个服务中有 Feign 客户端和一个方法

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
 MyDto uploadDocument(@RequestPart("file") MultipartFile file,
                               @RequestPart("myDto") String myDto);

我在另一个服务中有一个控制器

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<MyDto> uploadDocument(@RequestParam("file") MultipartFile file,
                                                      @RequestPart("myDto") MyDto myDto) {
.... some code here
    }

我面临的问题是 Feign 发送 myDto 的 Content-type : text/plain 并且我有 HttpMediaTypeNotSupportedException

是否可以使用 Content-type 发送@RequestPart("myDto") String myDto : application/json ?

预期的原始请求:

----------------------------boundary
Content-Disposition: form-data; name="file"; filename="fileName"
<file>
----------------------------boundary
Content-Disposition: form-data; name="myDto"
**Content-Type: application/json**
{"myDto": ""}

当前原始请求:

----------------------------boundary
Content-Disposition: form-data; name="file"; filename="fileName"
<file>
----------------------------boundary
Content-Disposition: form-data; name="myDto"
**Content-Type: text/plain**
{"myDto": ""}

【问题讨论】:

  • 您能否将Feign 客户端中的myDto 类型从String 更改为MyDto
  • 它不起作用,在这种情况下我收到 MissingServletRequestPartException
  • 也许这个issue 会有所帮助。你需要使用feign-form
  • 谢谢,但他们在控制器中使用字符串。我的目标是使用 MyDto 对象

标签: java spring-cloud-feign feign


【解决方案1】:

通过替换 feign-form PojoWriter 来解决这个问题。默认情况下,它将对象的每个字段序列化为单独的部分。

    @Bean
    public Encoder feignEncoder () {
        return new MyFormEncoder(objectMapper, new SpringEncoder(messageConverters));
    }
public class MyFormEncoder extends SpringFormEncoder {
    /**
     * Constructor with specified delegate encoder.
     *
     * @param delegate  delegate encoder, if this encoder couldn't encode object.
     */
    public MyFormEncoder(ObjectMapper objectMapper, Encoder delegate) {
        super(delegate);

        val processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART);
        processor.addFirstWriter(new MyPojoWriter(objectMapper));
    }
}
@FieldDefaults(level = PRIVATE, makeFinal = true)
public class MyPojoWriter extends AbstractWriter {

    private ObjectMapper objectMapper;

    public MyPojoWriter(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public boolean isApplicable(Object object) {
        return isUserPojo(object);
    }

    @Override
    protected void write(Output output, String key, Object value) throws EncodeException {
        var data = "";
        try {
            data = objectMapper.writeValueAsString(value);
        } catch (JsonProcessingException e) {
        }
        val string = new StringBuilder()
                .append("Content-Disposition: form-data; name=\"").append(key).append('"').append(CRLF)
                .append("Content-Type: application/json; charset=").append(output.getCharset().name()).append(CRLF)
                .append(CRLF)
                .append(data)
                .toString();

        output.write(string);
    }

    private boolean isUserPojo(@NonNull Object object) {
        val type = object.getClass();
        val typePackage = type.getPackage();
        return typePackage != null && typePackage.getName().startsWith("com.my-package.");
    }
}

【讨论】:

    【解决方案2】:

    更新到 2021 年。

    //spring-cloud-openfeign-core
    import org.springframework.cloud.openfeign.support.JsonFormWriter;
    
    
    @Import(JsonFormWriter.class)
    public class MyConfig {
    
    @Bean
    Encoder feignEncoder(JsonFormWriter jsonFormWriter) {
        return new SpringFormEncoder() {{
                var processor = (MultipartFormContentProcessor) getContentProcessor(ContentType.MULTIPART);
                processor.addFirstWriter(jsonFormWriter);
                processor.addFirstWriter(new SpringSingleMultipartFileWriter());
                processor.addFirstWriter(new SpringManyMultipartFilesWriter());
            }};
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多