|
|
Cuando definimos clases de tipo, podemos agregar anotaciones de variación al parámetro de tipo para afectar la variación de la clase de tipo y la capacidad del compilador para seleccionar instancias durante la resolución implícita.
La varianza se relaciona con los subtipos. Decimos que B es un subtipo de A si podemos usar un valor de tipo B en cualquier lugar donde esperamos un valor de tipo A.
Las anotaciones de covarianza y contravarianza surgen cuando se trabaja con constructores de tipos. Por ejemplo, denotamos la covarianza con un símbolo +:
trait F[+A] // the "+" means "covariant"
Se puede especificar exactamente qué instancia necesitamos. Sin embargo, esto no agrega valor en el código de producción. Es más simple y rápido usar las siguientes importaciones:
• import cats._ importa todas las clases de tipos de Cats de una sola vez;
• import cats.implicits._ importa todas las instancias de clase de tipo estándar y toda la sintaxis de una sola vez.
Podemos definir una instancia de Show simplemente implementando el trait :
import java.util.Date
implicit val dateShow: Show[Date] = new Show[Date] {
def show(date: Date): String = s"${date.getTime}ms since the epoch."
}
new Date().show
// res1: String = "1594650192117ms since the epoch."
Sin embargo, Cats también proporciona un par de métodos convenientes para simplificar el proceso. Hay dos métodos de construcción en el objeto complementario de Show que podemos usar para definir instancias para nuestros propios tipos:
object Show {
// Convert a function to a `Show` instance:
def show[A](f: A => String): Show[A] = ???
// Create a `Show` instance from a `toString` method:
def fromToString[A]: Show[A] = ???
}
Estos nos permiten construir instancias rápidamente con menos ceremonia que definirlas desde cero:
val implícito dateShow: Show[Date] = Show.show(date => s"${date.getTime}ms since the epoch.")
Como puede ver, el código que usa métodos de construcción es mucho más conciso que el código sin ellos. Muchas clases de tipos en Cats proporcionan métodos auxiliares como estos para construir instancias, ya sea desde cero o transformando instancias existentes para otros tipos.
Show proporciona un mecanismo para producir una salida de consola amigable para los desarrolladores sin usar toString. Aquí hay una definición abreviada:
package cats
trait Show[A] {
def show(value: A): String
}
Ahora tenemos acceso a dos instancias de Show y podemos usarlas para imprimir Ints y Strings:
val intAsString: String = showInt.show(123)
// intAsString: String = "123"
val stringAsString: String = showString.show("abc")
// stringAsString: String = "abc"
Spring Cloud generará dinámicamente una clase de proxy que se utilizará para invocar el servicio REST de destino. No se escribe ningún código para llamar al servicio que no sea una definición de interfaz.
Para habilitar el uso del cliente Feign se debe agregar una anotación, @EnableFeignClients, a la clase Application.java
Luego de habilitar el cliente de Feign, veamos una definición de interfaz de cliente de Feign que se puede usar para llama:
/*Package and import left off for conciseness*/
@FeignClient("ejemploService")
public interface EjemploFeignClient {
La gente mayor recordarán un framework que trabajaba de forma similar llamado cxf.
En la anotación @FeignClient le pasámos el nombre de la identificación del servicio que deseamos que represente la interfaz. A continuación, defimos un método, getEjemplo el cual retorna un objeto Ejemplo.
Como se puede ver la definición de la clase usa anotaciones de las cual ya estamos familiarizados.
Para usar la clase EjemploFeignClient, todo lo que necesitamos hacer es injectarla y usarla. El código de Feign Client se encargará de todo el trabajo de codificación.
Cuando utiliza la clase Spring RestTemplate estándar, todos los códigos de estado HTTP de las llamadas de servicio se devolverán a través del método getStatusCode() de la clase ResponseEntity. Con Feign Client, cualquier código de estado HTTP 4xx – 5xx devuelto por el servicio al que se llama se asignará a una FeignException. FeignException contendrá un cuerpo JSON que se puede analizar para el mensaje de error específico. Feign le brinda la capacidad de escribir una clase de decodificación de errores que asignará el error a una clase de excepción personalizada.
Dejo link : https://github.com/OpenFeign/feign
Para resolver este problema llego Raml, y veamos un ejemplo:
%RAML 1.0
title: Mobile Order API
baseUri: http://localhost:8081/api
version: 1.0
uses:
assets: assets.lib.raml
annotationTypes:
monitoringInterval:
type: integer
/orders:
displayName: Orders
get:
is: [ assets.paging ]
(monitoringInterval): 30
description: Lists all orders of a specific user
queryParameters:
userId:
type: string
description: use to query all orders of a user
post:
/{orderId}:
get:
responses:
200:
body:
application/json:
type: assets.Order
application/xml:
type: !include schemas/order.xsd
Dejo link: https://raml.org
El siguiente código muestra el método getRestTemplate() que creará el bean Spring RestTemplate respaldado por Ribbon.
package com.thoughtmechanix.licenses;
//...Most of import statements have been removed for consiceness
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
/*Package and import definitions left off for conciseness*/
@Component
Seguimos con el post anterior. Pero para no quedar tan colgado retomemos este código :
/*Packages and imports removed for conciseness*/
@Component
public class OrganizationDiscoveryClient {
@Autowired
private DiscoveryClient discoveryClient;
public Organization getOrganization(String organizationId) {
RestTemplate restTemplate = new RestTemplate();
List<ServiceInstance> instances = discoveryClient.getInstances("organizationservice");
if (instances.size()==0) return null;
String serviceUri = String.format("%s/v1/organizations/%s", instances.get(0).getUri().toString(),
organizationId);
ResponseEntity< Organization > restExchange = restTemplate.exchange(serviceUri,
HttpMethod.GET,
null, Organization.class, organizationId);
return restExchange.getBody();
}
}
Solo debemos usar Discovery-Client directamente cuando el servicio necesita consultar Ribbon para comprender qué servicios e instancias de servicio están registrados con él. Hay varios problemas con este código, incluidos los siguientes:
No se está aprovechando el balanceador de carga del lado del cliente de Ribbon: al llamar a Discovery-Client directamente, obtenemos una lista de servicios, pero tambien responsabilidad elegir qué instancias de servicio a invocar.
Se está haciendo demasiado trabajo: en este momento, debe crear la URL que se utilizará para llamar a su servicio. Es algo pequeño, pero cada pieza de código que puede evitar escribir es una pieza menos de código que tiene que depurar.
Es posible que los desarrolladores observadores de Spring hayan notado que está instanciando directamente la clase RestTemplate en el código. Esto es la antítesis de las invocaciones normales de Spring REST, ya que normalmente Spring Framework inyectaría RestTemplate en la clase que lo usa a través de la anotación @Autowired.
Ha creado una instancia de la clase RestTemplate porque una vez que haya habilitado Spring DiscoveryClient en la clase de aplicación a través de la anotación @EnableDiscovery-Client, todas las RestTemplates administradas por Spring Framework tendrán un interceptor habilitado para Ribbon. Al instanciar directamente la clase RestTemplate le permite evitar este comportamiento.
En resumen, existen mejores mecanismos para llamar a un servicio respaldado por Ribbon.
|
Me llego este mail y queria compartirlo :
|