欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用Spring Cloud Feign上传文件的示例

程序员文章站 2024-02-19 20:07:10
最近经常有人问spring cloud feign如何上传文件。有团队的新成员,也有其他公司的兄弟。本文简单做个总结—— 早期的spring cloud中,feign本身...

最近经常有人问spring cloud feign如何上传文件。有团队的新成员,也有其他公司的兄弟。本文简单做个总结——

早期的spring cloud中,feign本身是没有上传文件的能力的(1年之前),要想实现这一点,需要自己去编写encoder 去实现上传。现在我们幸福了很多。因为feign官方提供了子项目feign-form ,其中实现了上传所需的 encoder 。

注:笔者测试的版本是edgware.release。camden、dalston同样适应本文所述。

加依赖

<dependency>
 <groupid>io.github.openfeign.form</groupid>
 <artifactid>feign-form</artifactid>
 <version>3.0.3</version>
</dependency>
<dependency>
 <groupid>io.github.openfeign.form</groupid>
 <artifactid>feign-form-spring</artifactid>
 <version>3.0.3</version>
</dependency>


编写feign client

@feignclient(name = "ms-content-sample", configuration = uploadfeignclient.multipartsupportconfig.class)
public interface uploadfeignclient {
 @requestmapping(value = "/upload", method = requestmethod.post,
   produces = {mediatype.application_json_utf8_value},
   consumes = mediatype.multipart_form_data_value)
 @responsebody
 string handlefileupload(@requestpart(value = "file") multipartfile file);
 class multipartsupportconfig {
  @bean
  public encoder feignformencoder() {
   return new springformencoder();
  }
 }
}

如代码所示,在这个feign client中,我们引用了配置类multipartsupportconfig ,在multipartsupportconfig 中,我们实例化了springformencoder 。这样这个feign client就能够上传啦。

注意点

@requestmapping(value = "/upload", method = requestmethod.post,
   produces = {mediatype.application_json_utf8_value},
   consumes = mediatype.multipart_form_data_value)
中的produeces 、consumes 不能少;

接口定义中的注解@requestpart(value = "file") 不能写成@requestparam(value = "file" 。

最好将hystrix的超时时间设长一点,例如5秒,否则可能文件还没上传完,hystrix就超时了,从而导致客户端侧的报错。

springcloud中使用feign的坑

示例如下:

@feignclient("service-resource")
//@requestmapping("/api/test")
public interface testresourceitg {

 @requestmapping(value = "/api/test/raw", method = requestmethod.post, consumes = "application/x-www-form-urlencoded")
 public string raw1(@pathvariable("subject") string subject, // 标题
     @requestparam("content") string content); // 内容

}

说明:

*使用requestmapping中的consumes指定生成的请求的content-type
*requestparam指定的参数会拼接在url之后,如: ?name=xxx&age=18
*pathvariable指定的参数会放到一个linkedhashmap<string, ?>传入到feign的encoder中进行处理,而在spring中实现了该接口的encoder为springencoder,而该实现又会使用spring中的httpmessageconverter进行请求体的写入。

坑:

*不要在接口类名上使用requestmapping,虽然可以使用,但同时springmvc会把该接口的实例当作controller开放出去,这个可以在启动的mapping日志中查看到
*使用默认的springencoder,在不指定consumes时,pathvariable中的参数会生成json字符串发送,且默认情况下不支持form表单的生成方式,原因为:formhttpmessageconverter只能处理multivaluemap,而使用pathvariable参数被放在了hashmap中。默认更不支持文件上传。其实已经有支持处理各种情况的httpmessageconverter存在。

填坑:

*支持form表单提交:只需要编写一个支持map的formhttpmessageconverter即可,内部可调用formhttpmessageconverter的方法简化操作。
*支持文件上传:只需要把要上传的文件封装成一个resource(该resource一定要实现filename接口,这个是把请求参数解析成文件的标识),使用默认的resourcehttpmessageconverter处理即可。
*支持处理multipartfile参数:编写一个支持multipartfile的multipartfilehttpmessageconverter即可,内部可调用resourcehttpmessageconverter实现,同时注意需要将其添加至formhttpmessageconverter的parts中,并重写formhttpmessageconverter的getfilename方法支持从multipartfile中获取filename
*所有的httpmessageconverter直接以@bean的方式生成即可,spring会自动识别添加

完美支持表单和文件上传:

方案一:

使用附件中的mapformhttpmessageconverter.java和multipartfilehttpmessageconverter.java

在spring中进行如下配置即可

@bean
public mapformhttpmessageconverter mapformhttpmessageconverter(multipartfilehttpmessageconverter multipartfilehttpmessageconverter) {
 mapformhttpmessageconverter mapformhttpmessageconverter = new mapformhttpmessageconverter();
 mapformhttpmessageconverter.addpartconverter(multipartfilehttpmessageconverter);
 return mapformhttpmessageconverter;
}

@bean
public multipartfilehttpmessageconverter multipartfilehttpmessageconverter() {
 return new multipartfilehttpmessageconverter();
}

方案二:

使用feignspringformencoder.java

在spring中配置如下:

@bean
public encoder feignencoder(objectfactory<httpmessageconverters> messageconverters) {
 return new feignspringformencoder(messageconverters);
} 

推荐使用方案一

方案二为参考而来,未测

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。