Declarative HTTP Client in Spring Cloud – OpenFeign

What is OpenFeign

OpenFeign (originally Netflix Feign) is a declarative REST client that integrates:

  • Ribbon: Client-side load balancing
  • Eureka: Service discovery

OpenFeign = “Interface Proxy” for microservice calls, where you only need to define an interface, and Feign automatically generates the implementation class, completing service discovery + load balancing + HTTP calls automatically!

Advantages of OpenFeign

  • No need to write RestTemplate code
  • Interface as client, call remote services like local methods
  • Automatic integration of load balancing (by service name)
  • Supports request/response interception, logging, retries, circuit breaking, etc.

Code Example

1. Add Dependencies (Maven)

<!-- openfeign -->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>

  <!-- eureka -->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  </dependency>

  <!-- web -->
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

2. Enable Feign (Main Startup Class)

@EnableFeignClients: Enable Feign client scanning

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OpenFeignApplication1 {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignApplication1.class, args);
    }
}

3. Define Feign Interface (like writing DAO)

@FeignClient attributes:

  • value/name: Service name (must match spring.application.name)
  • path: Unified prefix for all methods, path = “/user”
  • configuration: Custom configuration class, configuration = FeignConfig.class
@Component
@FeignClient(value = "service-provider", path = "user") 
public interface OpenFeignUserService {

    @GetMapping("/{id}") // Actual call to "/user/{id}"
    Result<User> getUserById(@PathVariable("id") Long id);
}

✅ Feign will automatically:

  • Get the instance list of service-provider from Eureka

  • Select an instance via Ribbon / LoadBalancer

  • Initiate HTTP requests and parse JSON responses into User objects

See the previous article: Spring Cloud Service Registration and Discovery Center – Eureka, where the service name of the service provider registered in Eureka Client is “service-provider”:

server:
  port: 10001

spring:
  application:
    name: service-provider

eureka:
  client:
    register-with-eureka: true # Whether to register with Eureka Server
    fetch-registry: true # Whether to pull the service registry from Eureka Server (i.e., discover other services)
    service-url:
      defaultZone: http://eureka9992.com:9992/eureka/,http://eureka9991.com:9991/eureka/

4. Use Directly in Business Code

@RestController
@RequestMapping("/openfeign/user")
public class OpenFeignUserController {

    @Resource
    private OpenFeignUserService userService; // Inject Feign interface

    @GetMapping("/{id}")
    public Result<User> getUserById(@PathVariable("id") Long id) {      
        // Call remote service like a local method!
        // No need for RestTemplate, no need to concatenate URL, no need to handle HTTP response
        return userService.getUserById(id); 
    }
}

OpenFeign Logging Configuration

Log Levels:

  • NONE: No logs (default)

  • BASIC: Only request method, URL, status code

  • HEADERS: + Request/Response headers

  • FULL: + Request/Response body (including JSON)

Create a configuration class

import feign.Logger;

@Configuration
public class OpenFeignConfig {

    @Bean
    public Logger.Level logger() {
        return Logger.Level.FULL;
    }
}

Associate the logging configuration class through the configuration attribute in the @FeignClient annotation:

@Component
@FeignClient(value = "service-provider", path = "user", configuration = OpenFeignConfig.class) 
public interface OpenFeignUserService {

    @GetMapping("/{id}") // Actual call to "/user/{id}"
    Result<User> getUserById(@PathVariable("id") Long id);
}

application.yml

logging:
  level:
    # Full path of Feign interface
    com.lxx.service.OpenFeignUserService: DEBUG 

OpenFeign Timeout Configuration

1. Global timeout configuration (effective for all Feign interfaces)

# Global timeout configuration (Ribbon timeout, OpenFeign defaults to rely on Ribbon)
ribbon:
  ConnectTimeout: 5000       # Connection timeout (milliseconds): Maximum wait time to establish a connection
  ReadTimeout: 10000         # Read timeout (milliseconds): Maximum time to wait for a response after the connection is established

2. Timeout configuration for specific services (higher priority than global)

  • If you need to configure timeout for a specific service (e.g., service-provider):
# Timeout configuration for service-provider service
service-provider:  # Service name (consistent with @FeignClient(name/value))
  ribbon:
    ConnectTimeout: 3000     # Connection timeout 3 seconds
    ReadTimeout: 6000        # Read timeout 6 seconds

Leave a Comment