SpringCloud微服务远程调用
远程调用openFeign
最近在工作时,用到了远程调用传递文件的情况。但是在用openFeign传输文件时,总是发送失败。后面调研了一下发现openFeign本身不支持文件传输,需要在发送方进行一些配置。
相关依赖
<!--openfeign远程调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
<!-- 用于feginclient上传文件的依赖-->
<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>
配置feignFormEncoder
@Configuration
public class MultipartSupportConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
}
简单说明一下:
HttpMessageConverters类是springMvc框架基于http序列化和反序列化的核心类
Http协议的处理过程:
TCP字节流 <—> HttpRequest/HttpResponse <—> 内部对象,就涉及这两种序列化。
- 在springmvc中第一步已经由Servlet容器帮我们处理了
- spirngmvc进行第二步操作(Http序列化/反序列化),Http序列化和反序列化的核心是HttpMessageConverter。用过老版本springmvc的可能有些印象,那时候需要在xml配置文件中注入MappingJackson2HttpMessageConverter这个类型的bean,告诉springmvc我们需要进行Json格式的转换,它就是HttpMessageConverter的一种实现。
openFeign本身不支持文件对象的转换,对SpringMvc原有的消息转换器(HttpMessageConverter)进行了自定义,从这个构造方法中点进去:
public class SpringFormEncoder extends FormEncoder {
public SpringFormEncoder() {
this(new Default());
}
public SpringFormEncoder(Encoder delegate) {
super(delegate);
MultipartFormContentProcessor processor = (MultipartFormContentProcessor)this.getContentProcessor(ContentType.MULTIPART);
processor.addFirstWriter(new SpringSingleMultipartFileWriter());
processor.addFirstWriter(new SpringManyMultipartFilesWriter());
}
相关知识点
ContentType和Accept
ContentType指的是服务器当前发送的数据是什么数据(服务器返回的数据格式)
- Accept
Accept指的是用来告诉服务器客户端接收的是什么类型的数据,只有发送该类型的数据才可以识别
@RequestMapping中的produces和consumes
- consumes
consumes参数用来限制Http请求的ContentType
- produces
produces参数用来限制Accept
举例说明:
@RequestMapping(
value = "/file/upload",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE,
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
SuccessResponse fileUpload(@RequestPart("file") MultipartFile file) throws Exception;
请求配置表达的意思就是,用户发送的数据类型是文件,但是接收只能是JSON格式的数据。
遇到的问题
java.lang.NoSuchMethodError: 'feign.Request$Body feign.Request.requestBody()
原因是SpringCloud和SpringBoot的版本不一致导致
spring-cloud-openfeign-core升级到2.2.2.RELEASE后,如果使用的是okhttp,则需要把feign-okhttp相应升级到10.9的版本,否则会报错误:
java.lang.NoSuchMethodError: 'feign.Request$Body feign.Request.requestBody()