Feign-form is basically used

This module adds support for encoding Application/X-www-form-urlencoded and multipart/form-data forms.

1. Add dependencies

Contains dependencies for your application:

1.1,Maven:

<dependencies>.<dependency>
    <groupId>io.github.openfeign.form</groupId>
    <artifactId>feign-form</artifactId>
    <version>3.8.0</version>
  </dependency>.</dependencies>
Copy the code

1.2,Gradle:

The compile 'IO. Making. Openfeign. Form: feign - form: 3.8.0'Copy the code

2, requirements

The FeIGN-form extension relies on OpenFeign and its specific version:

  • All versions of FeIGN-Form prior to 3.5.0 work with OpenFeign 9.*;
  • Starting with version 3.5.0 of Feign-Form, this module works with OpenFeign 10.1.0 and later.

Important: There is no backward compatibility, nor is there any guarantee that versions of Feign-Form after 3.5.0 will be used with OpenFeign prior to 10.*. OpenFeign was refactured in release 10, so the best approach – use the latest OpenFeign and Feign-Form versions.

Note:

  • Spring-cloud-openfeign used OpenFeign 9 prior to v2.0.3.RELEASE., and then use 10.. This dependency is already available in the appropriate version of the feign-form, so there is no need to specify it separately.
  • Spring-cloud-starter-feign is a deprecated dependency that always uses version 9.* of OpenFeign.

3, usage,

Add FormEncoder to feign.Builder like this:

SomeApi github = Feign.builder()
                      .encoder(new FormEncoder())
                      .target(SomeApi.class, "http://api.some.org");
Copy the code

In addition, you can decorate existing encoders like this, such as JsonEncoder:

SomeApi github = Feign.builder()
                      .encoder(new FormEncoder(new JacksonEncoder()))
                      .target(SomeApi.class, "http://api.some.org");
Copy the code

And use them together:

interface SomeApi {

  @RequestLine("POST /json")
  @Headers("Content-Type: application/json")
  void json (Dto dto);

  @RequestLine("POST /form")
  @Headers("Content-Type: application/x-www-form-urlencoded")
  void from (@Param("field1") String field1, @Param("field2") String[] values);
}
Copy the code

You can specify both types of encoding through the Content-Type header.

application/x-www-form-urlencoded

interface SomeApi {

  @RequestLine("POST /authorization")
  @Headers("Content-Type: application/x-www-form-urlencoded")
  void authorization (@Param("email") String email, @Param("password") String password);

  // Group all parameters within a POJO
  @RequestLine("POST /user")
  @Headers("Content-Type: application/x-www-form-urlencoded")
  void addUser (User user);

  class User { Integer id; String name; }}Copy the code

multipart/form-data

interface SomeApi {

  // File parameter
  @RequestLine("POST /send_photo")
  @Headers("Content-Type: multipart/form-data")
  void sendPhoto (@Param("is_public") Boolean isPublic, @Param("photo") File photo);

  // byte[] parameter
  @RequestLine("POST /send_photo")
  @Headers("Content-Type: multipart/form-data")
  void sendPhoto (@Param("is_public") Boolean isPublic, @Param("photo") byte[] photo);

  // FormData parameter
  @RequestLine("POST /send_photo")
  @Headers("Content-Type: multipart/form-data")
  void sendPhoto (@Param("is_public") Boolean isPublic, @Param("photo") FormData photo);

  // Group all parameters within a POJO
  @RequestLine("POST /send_photo")
  @Headers("Content-Type: multipart/form-data")
  void sendPhoto (MyPojo pojo);

  class MyPojo {

    @FormProperty("is_public")Boolean isPublic; File photo; }}Copy the code

In the example above, the sendPhoto method uses three different supported types with the photo parameter.

  • File will use the extension of File to detect content-Type;
  • Byte [] will use application/octet-stream as content-type;
  • FormData will use the content-type and fileName of FormData;
  • Client-side custom POJOs for grouping parameters (including the above types).

FormData is a custom object that wraps a byte[] and defines a Content-Type and fileName, as follows:

  FormData formData = new FormData("image/png"."filename.png", myDataAsByteArray);
  someApi.sendPhoto(true, formData);
Copy the code

4. Spring MultipartFile and Spring Cloud Netflix@feignClient support

You can also use the form encoder with Spring MultipartFile and @FeignClient. Include dependencies in the project’s POM.xml file:

<dependencies>
  <dependency>
    <groupId>io.github.openfeign.form</groupId>
    <artifactId>feign-form</artifactId>
    <version>3.8.0</version>
  </dependency>
  <dependency>
    <groupId>io.github.openfeign.form</groupId>
    <artifactId>feign-form-spring</artifactId>
    <version>3.8.0</version>
  </dependency>
</dependencies>
Copy the code
@FeignClient( name = "file-upload-service", configuration = FileUploadServiceClient.MultipartSupportConfig.class )
public interface FileUploadServiceClient extends IFileUploadServiceClient {

  public class MultipartSupportConfig {

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public Encoder feignFormEncoder (a) {
      return new SpringFormEncoder(newSpringEncoder(messageConverters)); }}}Copy the code

Or, if you don’t need Spring’s standard encoder:

@FeignClient( name = "file-upload-service", configuration = FileUploadServiceClient.MultipartSupportConfig.class )
public interface FileUploadServiceClient extends IFileUploadServiceClient {

  public class MultipartSupportConfig {

    @Bean
    public Encoder feignFormEncoder (a) {
      return newSpringFormEncoder(); }}}Copy the code

Thanks to the tF-Haotri-Pham feature, it utilizes the Apache Commons-Fileupload library to handle multi-part response parsing. The body data portion is stored in memory as a byte array. You want to use this feature, please message converters in decoder SpringManyMultipartFilesReader contained in the list, and let the Feign client returns a MultipartFile array:

@FeignClient( name = "${feign.name}", url = "${feign.url}" configuration = DownloadClient.ClientConfiguration.class )
public interface DownloadClient {

  @RequestMapping("/multipart/download/{fileId}")
  MultipartFile[] download(@PathVariable("fileId") String fileId);

  class ClientConfiguration {

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    public Decoder feignDecoder (a) { List<HttpMessageConverter<? >> springConverters = messageConverters.getObject().getConverters(); List<HttpMessageConverter<? >> decoderConverters =newArrayList<HttpMessageConverter<? >>(springConverters.size() +1);

      decoderConverters.addAll(springConverters);
      decoderConverters.add(new SpringManyMultipartFilesReader(4096));

      HttpMessageConverters httpMessageConverters = new HttpMessageConverters(decoderConverters);

      return new SpringDecoder(new ObjectFactory<HttpMessageConverters>() {

        @Override
        public HttpMessageConverters getObject(a) {
          returnhttpMessageConverters; }}); }}}Copy the code