1. 개요

이 튜토리얼에서는 Spring Boot 앱을위한 선언적 REST 클라이언트 인 Spring Cloud OpenFeign 에 대해 설명 합니다.

Feign 은 Feign 어노테이션 및 JAX-RS 어노테이션을 포함하는 플러그 가능한 어노테이션 지원으로 웹 서비스 클라이언트 작성을보다 쉽게합니다.

또한 Spring CloudSpring Web에서 사용되는 것과 동일한 HttpMessageConvertersSpring MVC 어노테이션에 대한 지원을 추가합니다 .

Feign을 사용할 때 좋은 점은 인터페이스 정의 외에 서비스를 호출하기위한 코드를 작성할 필요가 없다는 것입니다.

2. 의존성

먼저 Spring Boot 웹 프로젝트를 만들고 spring-cloud-starter-openfeign 의존성을 pom.xml 파일에 추가하는 것으로 시작 합니다.

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

또한 spring-cloud-dependencies 를 추가해야합니다 .

 <dependencyManagement>
     <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Maven Central 에서 spring-cloud-starter-openfeignspring-cloud-dependencies 의 최신 버전을 찾을 수 있습니다 .

3. 가짜 클라이언트

다음으로 기본 클래스에 @EnableFeignClients추가해야합니다 .

@SpringBootApplication
@EnableFeignClients
public class ExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

이 어노테이션을 통해 Feign 클라이언트임을 선언하는 인터페이스에 대한 구성 요소 스캔을 활성화합니다.

그런 다음 @FeignClient 어노테이션을 사용하여 Feign 클라이언트를 선언합니다 .

@FeignClient(value = "jplaceholder", url = "https://jsonplaceholder.typicode.com/")
public interface JSONPlaceHolderClient {

    @RequestMapping(method = RequestMethod.GET, value = "/posts")
    List<Post> getPosts();

    @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
    Post getPostById(@PathVariable("postId") Long postId);
}

이 예에서는 JSONPlaceHolder API 에서 읽도록 클라이언트를 구성했습니다 .

에 전달 된 인수 @FeignClient의 함께하면서 어노테이션, 필수, 랜덤의 클라이언트 이름 의 URL 인수, 우리가 API의 기본 URL을 지정합니다.

또한이 인터페이스는 Feign 클라이언트이므로 Spring 웹 어노테이션을 사용하여 도달하려는 API를 선언 할 수 있습니다.

4. 구성

이제 각 Feign 클라이언트가 사용자 지정 가능한 구성 요소 집합으로 구성되어 있음을 이해하는 것이 매우 중요합니다 .

Spring Cloud 는 다음 섹션에서 설명하는대로 사용자 정의 할 수 있는 FeignClientsConfiguration 클래스를 사용하여 각 명명 된 클라이언트에 대한 요구에 따라 새로운 기본 세트를 생성합니다 .

위의 클래스에는 다음 빈이 포함됩니다.

  • Decoder – Response 를 디코딩하는 데 사용되는 SpringDecoder 를 래핑 하는 ResponseEntityDecoder
  • 인코더 – SpringEncoder , RequestBody 인코딩에 사용
  • 로거 – Slf4jLogger 는 Feign에서 사용하는 기본 로거입니다.
  • Contract – 어노테이션 처리를 제공하는 SpringMvcContract
  • Feign-Builder – 구성 요소를 구성하는 데 사용되는 HystrixFeign.Builder
  • 클라이언트 – LoadBalancerFeignClient 또는 기본 Feign 클라이언트

4.1. 사용자 정의 Bean 구성

이러한 Bean 중 하나 이상을 사용자 정의하려면 @Configuration 클래스를 사용하여이를 재정의 한 다음 FeignClient 어노테이션에 추가 할 수 있습니다 .

@FeignClient(value = "jplaceholder",
  url = "https://jsonplaceholder.typicode.com/",
  configuration = MyClientConfiguration.class)
@Configuration
public class MyClientConfiguration {

    @Bean
    public OkHttpClient client() {
        return new OkHttpClient();
    }
}

이 예제에서는 Feign에게 HTTP / 2를 지원하기 위해 기본 클라이언트 대신 OkHttpClient를 사용하도록 지시 합니다.

Feign은 요청과 함께 더 많은 헤더를 보내는 ApacheHttpClient를 포함하여 다양한 사용 사례에 대해 여러 클라이언트를 지원합니다 ( 예 : 일부 서버에서 예상하는 Content-Length) .

이러한 클라이언트를 사용하려면 필요한 의존성을 pom.xml 파일 에 추가하는 것을 잊지 마십시오 . 예를 들면 다음과 같습니다.

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

우리의 최신 버전을 찾을 수 있습니다 체하다 - okhttp체하다-HttpClient를 메이븐 중앙에 있습니다.

4.2. 속성을 사용한 구성

@Configuration 클래스를 사용하는 대신 application.yaml 예제 와 같이 애플리케이션 속성을 사용하여 Feign clients를 구성 할 수 있습니다 .

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic

이 구성을 사용 하면 애플리케이션에서 선언 된 각 클라이언트에 대해 시간 제한을 5 초로 설정하고 로거 수준을 기본 으로 설정합니다.

마지막으로 모든 @FeignClient 개체 를 구성하기 위해 기본 클라이언트 이름으로 구성을 만들거나 구성에 대한 가짜 클라이언트 이름을 선언 할 수 있습니다.

feign:
  client:
    config:
      jplaceholder:

@Configuration 빈과 구성 속성 이 모두있는 경우 구성 속성이 @Configuration을 재정의 합니다.

5. 인터셉터

인터셉터를 추가하는 것은 Feign이 제공하는 또 다른 유용한 기능입니다.

인터셉터는 모든 HTTP 요청 / 응답에 대해 인증에서 로깅에 이르기까지 다양한 암시 적 작업을 수행 할 수 있습니다.

이 섹션에서는 자체 인터셉터를 구현하고 Spring Cloud OpenFeign에서 제공하는 인터셉터를 즉시 사용할 수 있습니다. 둘 다 각 요청에 기본 인증 헤더를 추가합니다 .

5.1. RequestInterceptor 구현

따라서 아래 스 니펫에서 사용자 정의 요청 인터셉터를 구현해 보겠습니다.

@Bean
public RequestInterceptor requestInterceptor() {
  return requestTemplate -> {
      requestTemplate.header("user", username);
      requestTemplate.header("password", password);
      requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
  };
}

또한 요청 체인에 인터셉터를 추가하려면이 빈을 @Configuration 클래스에 추가하거나 이전에 본 것처럼 속성 파일에 선언하면됩니다.

feign:
  client:
    config:
      default:
        requestInterceptors:
          com.baeldung.cloud.openfeign.JSONPlaceHolderInterceptor

5.2. BasicAuthRequestInterceptor 사용

또는 Spring Cloud OpenFeign이 제공 하는 BasicAuthRequestInterceptor 클래스를 사용할 수 있습니다 .

@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
    return new BasicAuthRequestInterceptor("username", "password");
}

그렇게 간단합니다! 이제 모든 요청에 ​​기본 인증 헤더가 포함됩니다.

6. Hystrix 지원

Feign은 Hystrix를 지원 하므로 활성화 한 경우 대체 패턴을 구현할 수 있습니다.

폴백 패턴을 사용하면 원격 서비스 호출이 실패 할 때 예외를 생성하는 대신 서비스 소비자가 대체 코드 경로를 실행하여 다른 수단을 통해 작업을 수행하려고합니다.

목표를 달성하려면 속성 파일에 feign.hystrix.enabled = true추가하여 Hystrix를 활성화해야 합니다.

이를 통해 서비스가 실패 할 때 호출되는 대체 메서드를 구현할 수 있습니다.

@Component
public class JSONPlaceHolderFallback implements JSONPlaceHolderClient {

    @Override
    public List<Post> getPosts() {
        return Collections.emptyList();
    }

    @Override
    public Post getPostById(Long postId) {
        return null;
    }
}

Feign에게 fallback 메서드가 제공되었음을 알리 려면 @FeignClient 어노테이션 에 fallback 클래스도 설정해야합니다 .

@FeignClient(value = "jplaceholder",
  url = "https://jsonplaceholder.typicode.com/",
  fallback = JSONPlaceHolderFallback.class)
public interface JSONPlaceHolderClient {
    // APIs
}

7. 로깅

각 Feign 클라이언트에 대해 로거가 기본적으로 생성됩니다.

로깅을 활성화하려면 클라이언트 인터페이스의 패키지 이름을 사용하여 application.propertie 파일 에서이를 선언해야합니다 .

logging.level.com.baeldung.cloud.openfeign.client: DEBUG

또는 패키지의 특정 클라이언트에 대해서만 로깅을 활성화하려면 전체 클래스 이름을 사용할 수 있습니다.

logging.level.com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient: DEBUG

Feign 로깅은 DEBUG 수준 에만 응답 합니다.

클라이언트별로 구성 할 수 있는 Logger.Level로깅 할 양을 나타냅니다.

@Configuration
public class ClientConfiguration {
    
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
}

선택할 수있는 4 가지 로깅 수준이 있습니다.

  • NONE – 기본값 인 로깅 없음
  • BASIC – 요청 방법, URL 및 응답 상태 만 기록
  • HEADERS – 요청 및 응답 헤더와 함께 기본 정보 기록
  • FULL – 요청과 응답 모두에 대한 본문, 헤더 및 메타 데이터를 기록합니다.

8. 오류 처리

Feign의 기본 오류 핸들러 인 ErrorDecoder.default 는 항상 FeignException을 발생 시킵니다 .

이제이 동작이 항상 가장 유용한 것은 아닙니다. 따라서 던져진 예외를 사용자 정의하기 위해 CustomErrorDecoder를 사용할 수 있습니다 .

public class CustomErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {

        switch (response.status()){
            case 400:
                return new BadRequestException();
            case 404:
                return new NotFoundException();
            default:
                return new Exception("Generic error");
        }
    }
}

그런 다음 이전에했던 것처럼 @Configuration 클래스에 빈을 추가 하여 기본 ErrorDecoder 를 대체해야합니다 .

@Configuration
public class ClientConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}

9. 결론

이 기사에서는 Spring Cloud OpenFeign과 간단한 샘플 애플리케이션의 구현에 대해 설명했습니다.

또한 클라이언트를 구성하는 방법, 요청에 인터셉터를 추가하는 방법, HystrixErrorDecoder를 사용하여 오류를 처리하는 방법을 살펴 보았습니다.

평소처럼이 자습서에 표시된 모든 코드 샘플 은 GitHub에서 사용할 수 있습니다.