本文共 4857 字,大约阅读时间需要 16 分钟。
在之前的博文中,我简单介绍了OpenFeign的使用方式。其中在请求传递参数时,可以使用@Param和@QueryMap注解。本篇博文我将介绍学习如何使用OpenFeign进行表单参数提交或者传输文件。
我们先看下之前示例中只使用@Param和@QueryMap的局限性:
@Param注解用来解析其他注解中的参数表达式,一般用于restful风格的请求方式中。@QueryMap注解则是用来定义参数的Map集合或者是POJO。这两种方式定义的参数在请求时都会直接拼接在连接中,如 http:xxx?name1=value1&name2=value2。在使用时我们希望以POST方式将参数以表单的形式提交。这里我做了以下尝试,将请求方式改为POST,并配置请求头ContentType为application/x-www-form-urlencoded,方法的参数使用@Param标记并使用默认的encoder。
@RequestLine("POST /test/hello2")@Headers("Content-Type: application/x-www-form-urlencoded")ResultPojo hello2Post(@Param("name") String name);
在执行时抛出异常,默认的ecoder不支持LinkedHashMap的编码:
feign.codec.EncodeException: class java.util.LinkedHashMap is not a type supported by this encoder.
可以发现只将ContentType设置为application/x-www-form-urlencoded并不能实现表单提交,我们需要配置特殊的encoder。对此,OpenFeign官方在项目中为我们提供了Form Encoder。
OpenFeign提供的该模块支持表单application/x-www-form-urlencoded 和 multipart/form-data 两种编码。
在使用前需要添加依赖:
io.github.openfeign.form feign-form 3.8.0
之后可以直接配置Encoder
HelloService service = Feign.builder() .logger(new Slf4jLogger()) .logLevel(Logger.Level.FULL) .client(new OkHttpClient())// .encoder(new JacksonEncoder()) .encoder(new FormEncoder()) .decoder(new JacksonDecoder()) .requestInterceptor(new HeadersInterceptor()) .errorDecoder(new CustomErrorDecoder()) .retryer(new MyRetryer(5)) .exceptionPropagationPolicy(ExceptionPropagationPolicy.UNWRAP) .target(HelloService.class, "http://localhost:8080/");
可以看到我把之前的JacksonEncoder注释后,新配置了FormEncoder。但是我又希望同时使用这两种Encoder,OpenFeign对此也进行了支持,FormEncoder装饰JacksonEncoder,在FormEncoder类内部将另一个Ecoder对象作为类成员。
public class FormEncoder implements Encoder { private static final String CONTENT_TYPE_HEADER = "Content-Type"; private static final Pattern CHARSET_PATTERN = Pattern.compile("(?<=charset=)([\\w\\-]+)"); private final Encoder delegate; private final Mapprocessors; public FormEncoder() { this(new Default()); } public FormEncoder(Encoder delegate) { this.delegate = delegate; List list = Arrays.asList(new MultipartFormContentProcessor(delegate), new UrlencodedFormContentProcessor()); this.processors = new HashMap(list.size(), 1.0F); Iterator var3 = list.iterator(); while(var3.hasNext()) { ContentProcessor processor = (ContentProcessor)var3.next(); this.processors.put(processor.getSupportedContentType(), processor); } } .....}
可以看到FormEncoder的无参构造函数也会创建默认的Encoder对象。我们可以使用以下方式进行配置:
.encoder(new FormEncoder(new JacksonEncoder()))
注意,在使用FormEncoder时,必须配置ContentType。FormEncoder支持两种类型:
在配置Header后,方法的参数我们可以使用@Param注解或者是参数类POJO
@RequestLine("POST /test/hello2")@Headers("Content-Type: application/x-www-form-urlencoded")ResultPojo hello2Post(@Param("name") String name);@RequestLine("POST /test/hello2")@Headers("Content-Type: application/x-www-form-urlencoded")ResultPojo hello2Post2(ParamPojo paramPojo);
与之前相同,Pojo的变量名将被作为key。
在上传文件时需要使用该类型的Content-Type,OpenFeign也提供了几种使用方式:
@RequestLine("POST /test/file")@Headers("Content-Type: multipart/form-data")String uploadFile(@Param("file") File file);@RequestLine("POST /test/bytedata")@Headers("Content-Type: multipart/form-data")String uploadByteData(@Param("bytedata") byte[] data);@RequestLine("POST /test/formdata")@Headers("Content-Type: multipart/form-data")String uploadByFormData(@Param("file") FormData formData);@RequestLine("POST /test/formpojo")@Headers("Content-Type: multipart/form-data")String uploadByPojo(FilePojo filePojo);
在上传文件时,文件可以支持几种不同的方法参数类型进行传输。
FormData是OpenFeign定义的请求参数类,该类有是三个成员变量,分别为contentType, fileName, byte[] data。
@SuppressFBWarnings({"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})public class FormData { private String contentType; private String fileName; private byte[] data; ...}
在请求时会根据设置值作为Content-Type和fileName
FormData formData = new FormData("image/png", "filename.png", myDataAsByteArray);
服务端使用MultipartFile file作为接受参数,设置的fileName将作为文件的原始名称。
通过自定义POJO,可以将所有的请求参数组合到一起,使用@FormProperty来设置表单参数名称。服务端使用Multipart file和相应的参数进行接收。
public class FilePojo { @FormProperty("id") String id; @FormProperty("filename") File file; public FilePojo() { } public FilePojo(String id, File file) { this.id = id; this.file = file; }}
@RequestMapping("test/form-pojo")public String uploadPojo(@RequestParam(value = "filename") MultipartFile file, @RequestParam(value = "id") String id) { return id + file.getOriginalFilename();}
至此,使用OpenFeign进行表单提交和文件上传的使用方式已经学习介绍完毕,更详细的内容请看。
源码地址:https://github.com/Edenwds/javaweb/tree/master/feigndemo
转载地址:http://rdeii.baihongyu.com/