Configurar el cliente de Fingir en Spring Boot

En este artículo, aprenderemos a configurar un pretendercliente en su proyecto Spring Boot para usar las API RESTFul de otros servicios.

Índice
  1. Visión de conjunto
  2. configuración del proyecto
    1. proyecto experto
    2. Proyecto Gradle
    3. Configuración de la implementación del cliente ficticio
  3. Activar cliente ficticio
  4. Crear un cliente falso
  5. Simulación de configuración del cliente
    1. Del archivo de propiedades
    2. Del archivo de clase de configuración
    3. Interceptor de solicitudes
    4. Configuración de proxy
    5. pretende conectar
  6. Consumir al cliente falso
  7. Prueba unitaria para cliente ficticio

Visión de conjunto

FeignClient es un Cliente REST declarativo en la aplicación web Spring Boot. El cliente REST declarativo significa que solo proporciona la especificación del cliente como una interfaz y Spring Boot se encarga de la implementación por usted.

FeignClient se usa para consumir puntos finales de API RESTFul expuestos por un tercero o microservicio.

Fingir vs RestTemplate

Es una alternativa a RestTemplate y tiene las siguientes ventajas sobre RestTemplate:-

  1. No necesita escribir clases de implementación para llamar a otros servicios, solo proporcione una especificación como interfaz
  2. Las configuraciones del cliente, como la codificación/descodificación, el tiempo de espera y el registro, se pueden realizar simplemente a través de archivos de propiedades.
  3. Las configuraciones del cliente también se pueden realizar desde el archivo de configuración de Java.
  4. Desarrollado por Netflix. Tiene un excelente soporte para trabajar con otras bibliotecas de nube de inicio como Hystrix, Eureka y Ribbon.
  5. Spring Boot admite la escritura de casos de prueba para Feign Client usando WireMock
  6. Proporcione soporte de datos alternativos en caso de que falle la llamada a la API.

configuración del proyecto

Para la configuración inicial de su proyecto Spring Boot, debe usar Spring Initializr. Elegir el Fingir abierto y lona de primavera como dependencias y corredor del talón del contrato como una dependencia de prueba.

proyecto experto

Puede hacer clic en el enlace a continuación para generar un proyecto Maven con dependencias preseleccionadas:

https://start.spring.io/#!type=maven-project&language=java&platformVersion=2.5.1.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=api&name=api&description=Create%20Feign%20Client%20to%20consume%20RESTFul %20APIs&packageName=com.example.api&dependencies=cloud-feign,web,cloud-contract-stub-runner

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

<!-- to write web client using OpenFeign -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!-- to write test class using junit jupiter -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

<!-- to write integration test and mock stub using WireMock -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
  <scope>test</scope>
</dependency>

Proyecto Gradle

Del mismo modo, puede hacer clic en el enlace a continuación para generar un proyecto Gradle con dependencias preseleccionadas:

https://start.spring.io/#!type=gradle-project&language=java&platformVersion=2.5.1.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=api&name=api&description=Create%20Feign%20Client%20to%20consume%20RESTFul %20APIs&packageName=com.example.api&dependencies=cloud-feign,web,cloud-contract-stub-runner

dependencies {
  // to write web layer
  implementation 'org.springframework.boot:spring-boot-starter-web'

  // to write web client using OpenFeign
  implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

  // to write test class using junit jupiter
  testImplementation 'org.springframework.boot:spring-boot-starter-test'

  // to write integration test and mock stub using WireMock
  testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-stub-runner'
}

Configuración de la implementación del cliente ficticio

Spring Cloud OpenFeign admite tres implementaciones subyacentes para el cliente ficticio:

  • Culpa
    Esto está habilitado de forma predeterminada cuando no se proporciona ninguna configuración adicional.
  • ApacheHttpCliente
    Esto se activa cuando tenemos feign.httpclient.enabled: true propiedad en el archivo de configuración y io.github.openfeign:feign-httpclient en el classpath del proyecto

    application.yml

    feign.httpclient.enabled: true

    pom.xml

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

    build.gradle

    dependencies { implementation 'io.github.openfeign:feign-httpclient' }
  • OkHttpCliente
    Esto se activa cuando tenemos feign.okhttp.enabled: true propiedad en el archivo de configuración y io.github.openfeign:feign-okhttp en el classpath del proyecto

    application.yml

    feign.okhttp.enabled: true

    pom.xml

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

    build.gradle

    dependencies { implementation 'io.github.openfeign:feign-okhttp' }

Activar cliente ficticio

Cuando trabaja con el proyecto Spring Boot, no tiene que hacer nada para habilitar FeignClient para su proyecto. Asegurarse:-

  1. Teneis spring-boot-starter-web y spring-cloud-starter-openfeign dependencias en su pom.xml Donde construir.gradle
  2. Usted utiliza @SpringBootApplication y @EnableFeignClients anotaciones en el archivo de clase de inicio de su aplicación ApiApplication.

Spring Boot es obstinado, cuando ve el la tela y abierto falso dependencias en el classpath, configura toda la configuración predeterminada necesaria requerida para FeignClient y busca automáticamente las clases anotadas con @FeignClient

package com.example.api;

@SpringBootApplication
@EnableFeignClients
public class ApiApplication {

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

Crear un cliente falso

A continuación, crearemos un FeignClient para consumir desde el extremo de la API RESTFul. Vamos a crear un PostFeignClient interfaces-

  1. Anotado con @FeignClient qué escaneo automático mediante la aplicación Spring Boot para generar un cliente falso
  2. Este FeignClient consume API de esta URL: https://jsonplaceholder.typicode.com/

Mantengamos la URL de la API en el archivo de propiedades (por ejemplo, aplicación.yml) y usa esta propiedad:-

client:
  post:
    baseUrl: https://jsonplaceholder.typicode.com
package com.example.api.client;

@FeignClient(name = "postFeignClient", url = "${client.post.baseUrl}")
public interface PostFeignClient {
    @GetMapping("/posts")
    List<Post> getAllPosts();

    @GetMapping("/posts/{postId}")
    Post getPostById(@PathVariable Long postId);

    @GetMapping("/posts")
    List<Post> getPostByUserId(@RequestParam Long userId);

    @PostMapping("/posts")
    Post createPost(Post post);

    @PutMapping("/posts")
    Post updatePost(Post post);

    @DeleteMapping("/posts/{postId}")
    Post deletePost(@PathVariable Long postId);
}

Simulación de configuración del cliente

Del archivo de propiedades

La bota de resorte viene con culpa configuraciones globales que se aplican a todos los clientes falsos que cree. Lo bueno es que puede cambiar estas configuraciones globales desde el archivo de propiedades, como el tiempo de espera de conexión, el tiempo de espera de reproducción y el nivel de la grabadora.

aplicación.yml
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: BASIC

También puede configurar cada cliente ficticio individualmente desde el archivo de propiedades usando el cliente ficticio nombre o valor. Recuerde, creamos nuestro cliente falso con el nombre @FeignClient(name = "postFeignClient", ...)

Las siguientes propiedades se pueden configurar para cada cliente ficticio usando nombre o valor (por ejemplo postFingirCliente):-

feign:
  client:
    config:
      postFeignClient:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: FULL
        errorDecoder: com.example.SimpleErrorDecoder
        retryer: com.example.SimpleRetryer
        requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false
        encoder: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
        contract: com.example.SimpleContract

Del archivo de clase de configuración

También podemos configurar un FeignClient usando una clase de configuración. Debe pasar esta clase como configuración al crear FeignClient, p. @FeignClient(configuration = "FeignClientConfig.class", ...)

package com.example.api.client;

import com.example.api.config.FeignClientConfig;
@FeignClient(name = "postFeignClient", configuration = FeignClientConfig.class, url = "${client.post.baseUrl}")
public interface PostFeignClient {}

Dentro FeignClientConfigpuedes crear frijoles a partir de Decoder, Encoder, Logger, Contract, Feign.Builder y Client para reemplazar los beans predeterminados creados por Spring Boot. También puede crear frijoles a partir de Logger.Level, Retryer, ErrorDecoder y RequestInterceptor para incluir estas características.

package com.example.api.config;

public class FeignClientConfig {}

Spring Cloud Netflix proporciona los siguientes beans predeterminados para fingir (BeanType beanName: ClassName):

  • Decoder fingirDecodificador: ResponseEntityDecoder (que envuelve un SpringDecoder)
  • Encoder Codificador simulado: SpringEncoder
  • Logger fingir registrador: Slf4jLogger
  • Contract contrato falso: SpringMvcContract
  • Feign.Builder fingirconstructor: HystrixFeign.Builder
  • Client fingirCliente: si la cinta está habilitada, esta es una LoadBalancerFeignClientde lo contrario, se utiliza el cliente ficticio predeterminado.

Spring Cloud Netflix no proporciona los siguientes beans de forma predeterminada para fingir, pero siempre busca beans de estos tipos en el contexto de la aplicación para crear el cliente ficticio:

  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • RequestInterceptor
  • SetterFactory

Interceptor de solicitudes

Es posible que se encuentre con un caso de uso en el que necesite pasar encabezados de autorización o solicitar encabezados en llamadas API usando Fingir cliente.

En este caso, debe proporcionar un bean de tipo RequestInterceptor en una clase de configuración de cliente fingido para, p. FeignClientConfig clase de la siguiente manera: -

package com.example.api.config;

public class FeignClientConfig {

    /**
     * Enable this bean if you want to add headers in HTTP request
     */
    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            requestTemplate.header("Content-Type", "application/json");
            requestTemplate.header("Accept", "application/json");
            requestTemplate.header("header_1", "value_1");
            requestTemplate.header("header_2", "value_2");
            requestTemplate.header("header_3", "value_3");
        };
    }

    /**
     * Enable this bean if you want to add basic Authorization header
     * for e.g. Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
     */
    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("username", "password");
    }
}

Nota: - No anote esta clase con @Configuration anotación, de lo contrario, esta configuración se volverá global, es decir, todos los clientes ficticios heredarán esta configuración en este caso.

Una vez que aplique esta configuración a FeignClient, todas las solicitudes realizadas por este FeignClient incluirán los encabezados comunes y el encabezado de autorización básico para las solicitudes HTTP salientes.

Configuración de proxy

Es posible que se encuentre con un caso de uso en el que el cliente de Feign necesite usar un proxy HTTP para realizar la llamada a la API de salida.

En este caso, debe anular el valor predeterminado Client bean en una clase de configuración de cliente fingido para, p. FeignClientConfig clase de la siguiente manera: -

package com.example.api.config;

public class FeignClientConfig {

    /**
     * Enable this bean if you want to setup HTTP proxy for Default Feign Client
     */
    @Bean
    public Client feignClient() {
      return new Client.Proxied(null, null, 
          new Proxy(Proxy.Type.HTTP,
              new InetSocketAddress(proxyHost, proxyPort)));
    }

    /**
     * Enable this bean if you want to setup HTTP proxy for ApacheHttpClient Feign Client
     */
    @Bean
    public CloseableHttpClient feignClient() {
      return HttpClientBuilder.create().setProxy(
          new HttpHost(proxyHost, proxyPort)).build();
    }

    /**
     * Enable this bean if you want to setup HTTP proxy for OkHttpClient Feign Client
     */
    @Bean
    public OkHttpClient okHttpClient() {
      return new OkHttpClient.Builder()
          .proxy(new Proxy(Proxy.Type.HTTP, 
              new InetSocketAddress(proxyHost, proxyPort)))
          .build();
    }
}

Anote esta clase con @Configuration anotación, si desea aplicar esta configuración a todos los clientes ficticios del proyecto. De lo contrario, no anote ni aplique esta configuración a un Feign Client específico, todas las solicitudes realizadas por este FeignClient utilizarán el proxy dado para las solicitudes HTTP salientes.

pretende conectar

Se crea un registrador para cada FeignClient de forma predeterminada. El registro ficticio responde solo a DEPURAR nivel.

Para habilitar el registro ficticio para todos los clientes ficticios, establezca el nivel de registro del nombre del paquete de interfaces de cliente en DEBUG:-

logging:
  level:
    com.example.api.client: DEBUG

Para habilitar el registro ficticio para un FeignClient específico, declare el nivel de registro de esa interfaz para DEBUG:-

logging:
  level:
    com.example.api.client.PostFeignClient: DEBUG

Una vez que habilite el registro ficticio configurando el nivel de registro en DEBUG, puede controlar aún más el registro usando nivel de registrador propiedad de configuración que le dice a Fingir cuánto ahorrar por solicitud. Las opciones son:

  • NADASin registro (DEFAULT).
  • BÁSICORegistre solo el método de solicitud y la URL, junto con el código de estado de respuesta y el tiempo de ejecución.
  • ENCABEZADOSRegistre información básica con encabezados de solicitud y respuesta.
  • COMPLETORegistre encabezados, cuerpos y metadatos de solicitudes y respuestas.

Por ejemplo, loggerLevel BÁSICO para todos los clientes falsos y loggerLevel COMPLETO para postfingircliente:-

feign:
  client:
    config:
      default:
        loggerLevel: BASIC
	  postFeignClient:
        loggerLevel: FULL

Consumir al cliente falso

Ahora que hemos creado un cliente falso, creemos una clase de capa de servicio PostService y su implementación PostServiceImpl consumir estas API utilizando el cliente falso

public interface PostService {

	List<Post> getAllPosts();
	Post getPostById(Long postId);
	List<Post> getAllPostsByUserId(Long userId);
	Post createPost(Post post);
	void updatePost(Long postId, Post post);
	void deletePost(Long postId);
}
@Service
public class PostServiceImpl implements PostService {

    @Autowired
    private PostFeignClient postFeignClient;

    @Override
    public List<Post> getAllPosts() {
        return postFeignClient.getAllPosts();
    }

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

    @Override
    public List<Post> getAllPostsByUserId(Long userId) {
        return postFeignClient.getPostByUserId(userId);
    }

    @Override
    public Post createPost(Post post) {
        return postFeignClient.createPost(post);
    }

    @Override
    public void updatePost(Long postId, Post post) {
        postFeignClient.updatePost(post);
    }

    @Override
    public void deletePost(Long postId) {
        postFeignClient.deletePost(postId);
    }
}

Ahora que hemos creado nuestra clase de servicio y consumido las API usando un cliente ficticio. Vamos a crear un controlador PostController para probar nuestro cliente falso.

@RestController
@RequestMapping("/posts")
public class PostController {

    @Autowired
    private PostService postService;

    @GetMapping
    public List<Post> getAllPosts() { return postService.getAllPosts(); }

    @GetMapping("/{postId}")
    public Post getPostById(@PathVariable Long postId) { return postService.getPostById(postId); }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Post createPost(Post post) { return postService.createPost(post); }

    @PutMapping("/{postId}")
    @ResponseStatus(HttpStatus.OK)
    public void updatePost(@PathVariable Long postId, Post post) { postService.updatePost(postId, post); }

    @DeleteMapping("/{postId}")
    @ResponseStatus(HttpStatus.OK)
    public void deletePost(@PathVariable Long postId) { postService.deletePost(postId); }
}

Probemos el punto final de nuestro controlador desde el navegador para ver si el cliente de Fingir funciona.

Prueba de punto final de cliente falso

Eso es. Ha creado y probado con éxito un cliente ficticio para consumir API desde un punto final determinado.

Prueba unitaria para cliente ficticio

Siempre debe escribir casos de prueba para su cliente de Fingir. El módulo Spring Boot Cloud spring-cloud-contrat le permite usar WireMock en sus casos de prueba para simular datos de API.

Si su aplicación Spring Boot usa el servidor incorporado Tomcat predeterminado, puede agregar spring-cloud-starter-contract-stub-runner dependencia a su maven (o gradle) y agregue @AutoConfigureWireMock a nivel de clase para usar Wiremock en tus pruebas.

Wiremock se ejecuta como un servidor de código auxiliar y puede registrar el comportamiento del código auxiliar utilizando una API de Java o mediante declaraciones JSON estáticas como parte de su prueba. El siguiente código muestra un ejemplo:

aplicación-prueba.yml

Creamos un archivo de configuración de prueba para que nuestro FeignClient llamadas https://localhost:9091 para obtener los datos

client:
  post:
    baseUrl: http://localhost:9091
Examen de la unidad

Le decimos a WireMock que ejecute un stub en el puerto local 9091 para servir datos ficticios. De esta manera, nuestro FeignClient comienza a recibir datos del stub falso.

package com.example.api.client;

@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 9091)
public class PostFeignClientTest {

    @Autowired
    PostFeignClient postFeignClient;

    @Test
    public void getAllPosts_whenValidClient_returnValidResponse() throws Exception {
        // Using WireMock to mock client API:
        stubFor(get(urlEqualTo("/posts"))
                .willReturn(aResponse()
                        .withStatus(HttpStatus.OK.value())
                        .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
                        .withBody(read("stubs/posts.json"))));

        List<Post> posts = postFeignClient.getAllPosts();
        Post post = posts.get(0);

        // We're asserting if WireMock responded properly
        assertThat(posts).hasSize(10);
        assertThat(post.getId()).isEqualTo(1);
        assertThat(post.getUserId()).isEqualTo(1);
        assertThat(post.getTitle()).isEqualTo("title");
        assertThat(post.getBody()).isEqualTo("body");
    }

    private String read(String location) throws IOException {
        return IOUtils.toString(new ClassPathResource(location).getInputStream(), StandardCharsets.UTF_8);
    }
}

Descargue el código fuente completo para los ejemplos de este artículo desde github/springboot-api

Si quieres conocer otros artículos parecidos a Configurar el cliente de Fingir en Spring Boot puedes visitar la categoría Tutoriales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Esta página web utiliza cookies para analizar de forma anónima y estadística el uso que haces de la web, mejorar los contenidos y tu experiencia de navegación. Para más información accede a la Política de Cookies . Ver mas