什么是Feign
Feign是一个声明式、模板化的HTTP客户端,它简化了使用Spring Cloud服务的客户端开发。在微服务架构中,服务与服务之间的调用是通过HTTP RESTful API进行的。Feign提供了一种默认的方式来实现服务之间的调用,使得客户端的调用变得更加简单、优雅、可读性更好。
服务提供者API
引入依赖 在pom.xml中添加如下依赖:
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId><version>10.2.0</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>2.2.3.RELEASE</version></dependency>
创建Feign Client的API 创建一个Java接口,使用@FeignClient注解来指定服务提供者的名称。
@FeignClient(name = "feign-provider", value = "feign-provider", path = "/provider",url= "${feign-provider.url}")publicinterfaceFeignClientApi{
@GetMapping("/hello")
String sayHello();
}
打包Feign Client的API提供给服务消费者使用
服务消费者
引入依赖 在pom.xml中添加如下依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>2.2.3.RELEASE</version></dependency><dependency><groupId>com.fudai.spring.feign</groupId><artifactId>provider-api</artifactId></dependency>
属性配置
配置超时时间
feign.client.config.default.connectTimeout=5000
feign.client.config.default.readTimeout=5000
配置Feign Client的API服务提供者地址
feign-provider.url=127.0.0.1:8081
引入ServiceProviderClient依赖 在需要调用服务的类中,使用@Autowired注解来注入Feign Client,并直接调用其中的方法。
@Service@Slf4j
public class BizService {
@Autowired
private FeignClientApi feignClientApi;
publicvoidprocess() {
log.info("process 结果:{}", feignClientApi.sayHello());
}
}
springboot启动类中加入feign注解@EnableFeignClients
@SpringBootApplication(
scanBasePackages = {"com.fudai.spring.feign.consumer.*"})
@EnableFeignClients(basePackages = {"com.fudai.spring.feign.provider.api"})
public class Bootstrap {
publicstaticvoidmain(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
}
demo地址
https://github.com/fudai/feign-demo
使用中遇到的问题
问题描述:
使用multipart/form-data格式上传文件,报错: {"code":1,"error":"Content type 'multipart/form-data;boundary=r7J8EqF60I35iHU6qNbNnns8coGDoGuVA1s;charset=UTF-8' not supported","data":null,"success":false}
问题原因:
Feign默认情况下只支持Content-Type为application/x-www-form-urlencoded和application/json格式的请求,不支持Content-Type为multipart/form-data的请求。
解决方案:
使用Feign发送multipart/form-data格式的请求,需要使用Feign的multipart/form-data支持。
方案1: 如果请求参数是对象,对象中有List<MultipartFile>,可以在方法中使用注解: @Headers("Content-Type:multipart/form-data")
样例如下:
@PostMapping(value = "/testMultipart2", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)@Headers("Content-Type:multipart/form-data")
String testMultipart2(MultipartRequest request);
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class MultipartRequest{
private List<MultipartFile> files;
}
方案2:
如果请求参数直接是List<MultipartFile>对象,可以使用注解: @RequestPart("files")
修饰请求MultipartFile对象
样例如下:
@PostMapping(value = "/testMultipart1", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String testMultipart1(@RequestPart("files") List<MultipartFile> files);
方案1和方案2都需要@PostMapping注解上加上属性: consumes = MediaType.MULTIPART_FORM_DATA_VALUE 如果请求参数直接是单个MultipartFile对象或者 请求参数是对象,对象中有单个MultipartFile。只需要在@PostMapping注解上加上属性
样例如下:
@PostMapping(value = "/testMultipart3", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String testMultipart3(MultipartFile file);
@PostMapping(value = "/testMultipart4", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String testMultipart4(SingleMultipartRequest request);
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
class SingleMultipartRequest{
privateMultipartFilefile;
}