es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La mejor manera de añadir un RequestInterceptor a un solo FeignClient.

Necesito agregar un RequestInterceptor a un cliente Feign específico. El interceptor agregará información de autenticación que no quiero filtrar a un tercero, por lo tanto, no quiero que se active para TODOS los clientes Feign. Tengo esto funcionando, pero parece un poco desordenado y espero que haya una opción más limpia (menos código).

Espero que alguien pueda señalarme dónde puedo simplificar las cosas, especialmente en cuanto a las cosas del codificador/decodificador. Realmente no me gusta cómo ensucian el constructor de mis servicios y me parece extraño que incluso deban especificarse en primer lugar.

Tengo en mi archivo build.gradle:

implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

Tengo un RequestInterceptor que se ve así:

import feign.RequestInterceptor;
import feign.RequestTemplate;

public class BearerAuthRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        // ... OMITIR ... (solo agrega un encabezado Authorization)
    }
}

Tengo un FeignClient que se ve así:

@FeignClient(name = "myfeignclient")
public interface MyFeignClient {
    @GetMapping(value = "/doTheThing")
    String doTheThing();
}

Utilizo mi FeignClient desde un servicio de la siguiente manera:

@Service
@Import(FeignClientsConfiguration.class)
public class MyService {

    private final MyFeignClient myFeignClient;

    @Autowired
    public MyService(Decoder decoder, Encoder encoder, Contract contract) {
        this.myFeignClient = Feign.builder()
                .contract(contract)
                .encoder(encoder)
                .decoder(decoder)
                .requestInterceptor(new BearerAuthRequestInterceptor())
                .target(MyFeignClient.class, "https://whatever.com");
    }

    public void callTheFeignClient() {
        myFeignClient.doTheThing();
    }
}
Tags:  ,

Answer

  1. Avatar for davy.ai

    Una forma de simplificar este código es crear una configuración separada del FeignClient para MyFeignClient, donde se agrega el BearerAuthRequestInterceptor como RequestInterceptor específico solo para ese cliente. Aquí tienes un ejemplo de código:

    @Configuration
    public class MyFeignClientConfiguration {
    
      @Autowired
      private ObjectFactory<httpmessageconverters> messageConverters;
    
      @Bean
      public Decoder decoder() {
        return new ResponseEntityDecoder(new SpringDecoder(messageConverters));
      }
    
      @Bean
      public Encoder encoder() {
        return new SpringEncoder(messageConverters);
      }
    
      @Bean
      public Contract feignContract() {
        return new SpringMvcContract();
      }
    
      @Bean
      public BearerAuthRequestInterceptor bearerAuthRequestInterceptor() {
        return new BearerAuthRequestInterceptor();
      }
    
      @Bean
      public MyFeignClient myFeignClient(FeignBuilder feignBuilder) {
        return feignBuilder
          .requestInterceptor(bearerAuthRequestInterceptor()) // agregar interceptor específico
          .target(MyFeignClient.class, "https://whatever.com");
      }
    }
    
    @Service
    @Import(FeignClientsConfiguration.class)
    public class MyService {
    
      private final MyFeignClient myFeignClient;
    
      @Autowired
      public MyService(MyFeignClient myFeignClient) {
        this.myFeignClient = myFeignClient;
      }
    
      public void callTheFeignClient() {
          myFeignClient.doTheThing();
      }
    }
    

    En este ejemplo, creamos una clase de configuración separada para MyFeignClient llamada MyFeignClientConfiguration. Definimos los beans requeridos para FeignClient, es decir, Decoder, Encoder, Contract y BearerAuthRequestInterceptor, que es específico para MyFeignClient.

    También creamos una instancia de FeignClient llamada myFeignClient utilizando el FeignBuilder proporcionado a través de la autoinyección de dependencias. Aquí, especificamos el BearerAuthRequestInterceptor como un interceptor de solicitud solo para este cliente, mientras que otros FeignClients no tendrán este interceptor.

    Luego, en la clase MyService, en lugar de crear una instancia de FeignClient utilizando Feign.builder(), podemos inyectar directamente la instancia de MyFeignClient y usarla.

    Este enfoque nos permite mantener la lógica del BearerAuthRequestInterceptor separada y específica para MyFeignClient, manteniendo la clase MyService limpia y concisa.

Comments are closed.