Master Spring Cloud OpenFeign: Complete Guide with Code Samples
This article provides a comprehensive introduction to Spring Cloud OpenFeign, comparing it with Feign and HttpExchange, and walks through practical setup, client declaration, custom configuration, interceptors, error handling, timeout and logging settings with full code examples for Spring Boot 3.2.5.
1. Introduction
OpenFeign is a declarative HTTP client that simplifies writing network service clients. By annotating an interface, you can call other services without writing boilerplate code. It supports both OpenFeign and Jakarta JAX‑RS annotations.
The article offers a full‑stack overview of Spring Cloud OpenFeign.
2. Practical Example
2.1 Add Dependency
<code><dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2022.0.3</version>
</dependency></code>Choose the Cloud version that matches your Spring Boot version.
2.2 Enable Feign Clients
<code>@SpringBootApplication
@EnableFeignClients(basePackages = "com.pack.feign")
public class AppApplication {
}
</code>If the annotation is placed on the main class, the basePackages attribute can be omitted.
2.3 Declare Feign Client
<code>@FeignClient(value = "userFeignClient", url = "http://localhost:8088")
public interface UserFeignClient {
@GetMapping("/users")
ResponseEntity<List<User>> getUsers();
}
</code>value specifies the client name (required). url defines the base request URL. The @GetMapping annotation maps the target endpoint.
2.4 Invoke the Client
<code>private final UserFeignClient userFeignClient;
public UserFeignController(UserFeignClient userFeignClient) {
this.userFeignClient = userFeignClient;
}
ResponseEntity<List<User>> response = userFeignClient.getUsers();
if (response.getStatusCode().is2xxSuccessful()) {
List<User> users = response.getBody();
users.forEach(System.out::println);
} else if (response.getStatusCode().is4xxClientError()) {
throw new BadRequestException("Bad Request");
} else {
throw new RuntimeException("Server Error");
}
</code>The client is injected like any other Spring bean.
2.5 Inheritance
Common functionality can be placed in a base interface and extended:
<code>@FeignClient(value = "accountFeignClient", url = "http://localhost:8088/")
public interface AccountFeignClient extends UserFeignClient {
@GetMapping("/account/{id}")
String getAccountByUser(@PathVariable("id") Long id);
}
</code>Multi‑level inheritance is not supported.
2.6 OpenFeign Configuration
Default components are defined in FeignClientsConfiguration and can be overridden.
Decoder – ResponseEntityDecoder (wraps SpringDecoder )
Encoder – SpringEncoder
Logger – Slf4jLogger
Contract – SpringMvcContract
Retryer – configurable retry strategy
Client – global request handler
Custom configuration example:
<code>public class PackAccountFeignConfiguration {
@Bean
public CloseableHttpClient feignClient() {
return HttpClients.createDefault();
}
}
</code>Use the custom configuration in the client annotation:
<code>@FeignClient(value = "accountFeignClient",
url = "http://localhost:8088/",
configuration = PackAccountFeignConfiguration.class)
public interface AccountFeignClient extends UserFeignClient {}
</code>Add the required dependency for the Apache HttpClient:
<code><dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hc5</artifactId>
</dependency>
</code>2.7 Property‑Based Configuration
Override settings via application.yml :
<code>spring:
cloud:
openfeign:
config:
default:
connectTimeout: 5000
read-timeout: 5000
</code>Specific client configuration:
<code>spring:
cloud:
openfeign:
config:
accountFeignClient:
connectTimeout: 5000
</code>When both a @Configuration bean and properties are present, properties take precedence unless spring.cloud.openfeign.client.default-to-properties is set to false .
2.8 Interceptor Configuration
<code>@Bean
RequestInterceptor requestInterceptor() {
return template -> template.header("requestID", "UUID");
}
</code>Allows adding custom headers or authentication logic.
2.9 Error Handling
<code>@Bean
ErrorDecoder errorDecoder() {
return (methodKey, response) -> switch (response.status()) {
case 400 -> new BadRequestException(response);
case 429 -> new TooManyRequestsException(response);
default -> new Exception("feign client exception");
};
};
</code>Provides fine‑grained exception handling based on HTTP status.
2.10 Logging
Enable logging via properties:
<code>logging:
level:
com.pack.feign: DEBUG
</code>Or for a specific client:
<code>logging:
level:
com.pack.feign.AccountFeignClient: DEBUG
</code>Define logger level bean for full logging:
<code>@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
</code>Supported levels: NONE, BASIC, HEADERS, FULL.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.