Spring Cloud Feign Deep Dive: Architecture, Usage, and Practical Demo
This article walks through the background of Spring Cloud's Feign client, explains its core concepts, shows step‑by‑step project setup with Eureka services, demonstrates remote calls and file upload extensions using Feign‑Form, and concludes with a functional microservice example.
1. Background
In a previous article we introduced Ribbon, the core client‑side load‑balancing component of Spring Cloud, which selects a service instance from multiple providers based on a rule. Building on that knowledge, we now explore another core component, Spring Cloud Feign.
2. Feign Overview
Spring Cloud Feign is an HTTP client built on Netflix Feign. It simplifies development and maintenance of HTTP clients by allowing developers to declare a Java interface annotated with @FeignClient. Under the hood it still uses Apache HttpClient or OkHttp to send requests. Compared with native Feign, Spring Cloud Feign adds support for Spring MVC annotations, integrates Ribbon for client‑side load balancing, and can work with Hystrix for circuit breaking.
3. Implementation
First, create the following Maven projects (the code is omitted for brevity): eureka-server, eureka-provider-1, eureka-provider-2, and a consumer project named eureka-consumer-feign. Add Feign dependencies to the consumer’s pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>Enable Feign scanning in the consumer’s main class:
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}Define a Feign client interface:
@FeignClient(name = "eureka-provider")
public interface RpcService {
@RequestMapping(value = "/hello")
String hello();
}Create a controller that uses the client:
@RestController
public class HelloController {
@Autowired
private RpcService rpcService;
@GetMapping("/rpc")
public String rpc() {
String result = rpcService.hello();
return "发起远程调用,收到返回的信息:" + result;
}
}Start the four services ( eureka-server, eureka-provider-1, eureka-provider-2, eureka-consumer-feign) and visit http://localhost:9003/rpc in a browser. The response shows that the client calls the target interface in a round‑robin fashion.
4. File Transfer with Feign
By default Feign handles most HTTP requests, but it does not support direct file upload. To enable this, add the feign-form and feign-form-spring dependencies (version 3.0.3) to the consumer’s pom.xml:
<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>Provider side: implement a standard Spring MVC file‑upload endpoint:
@RestController
public class HelloController {
private static final String SRC_PATH = "/Users/demo/file/";
@PostMapping("/fileUpload")
public String fileUpload(@RequestParam("file") MultipartFile file,
@RequestParam("prefixName") String prefixName) throws IOException {
String fileName = file.getOriginalFilename();
String absolutePath = SRC_PATH + prefixName + "_" + fileName;
file.transferTo(new File(absolutePath));
return "Upload file success:" + prefixName + "_" + fileName;
}
}Consumer side: define a Feign client that consumes multipart/form-data:
@FeignClient(name = "eureka-provider", configuration = FeignSupportConfig.class)
public interface RpcUploadService {
@PostMapping(value = "/fileUpload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String handleFileUpload(@RequestPart("file") MultipartFile file,
@RequestParam("prefixName") String prefixName);
}Configure the encoder required by Feign‑Form:
@Configuration
public class FeignSupportConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
}Create a controller that invokes the upload client:
@RestController
public class HelloController {
@Autowired
private RpcUploadService rpcUploadService;
@PostMapping("/rpcUpload")
public String rpcUpload(@RequestParam("file") MultipartFile file) throws IOException {
String result = rpcUploadService.handleFileUpload(file, "feign");
return "通过 feign 发起文件远程上传调用,收到返回的信息:" + result;
}
}Start the services again and use Postman to call /rpcUpload. The response confirms successful remote file upload.
5. Summary
Feign is a lightweight HTTP client framework that enables concise and maintainable service calls. Within the Spring Cloud ecosystem it integrates Ribbon for automatic client‑side load balancing and Hystrix for circuit breaking (to be covered in a future article).
References
https://www.didispace.com/spring-cloud/spring-cloud-starter-dalston-2-4.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Pan Zhi's Tech Notes
Sharing frontline internet R&D technology, dedicated to premium original content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
