Introdução ao Spring Cloud OpenFeign
1. Visão geral
Neste tutorial, vamos descreverSpring Cloud OpenFeign - um cliente REST declarativo para aplicativos Spring Boot.
Feign torna a escrita de clientes de serviço da web mais fácil com suporte a anotações conectáveis, que inclui anotações Feign e anotações JAX-RS.
Além disso,Spring Cloud adiciona suporte paraSpring MVC annotationse para usar o mesmoHttpMessageConverters usado no Spring Web.
E, uma coisa ótima sobre o uso do Feign é que não precisamos escrever nenhum código para chamar o serviço, a não ser uma definição de interface.
2. Dependências
Primeiro, começaremos criando um projeto da web Spring Boot e adicionando a dependênciaspring-cloud-starter-openfeign ao nosso arquivopom.xml:
org.springframework.cloud
spring-cloud-starter-openfeign
Além disso, precisaremos adicionar ospring-cloud-dependencies:
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
Podemos encontrar as versões mais recentes despring-cloud-starter-openfeignespring-cloud-dependencies no Maven Central.
3. Cliente fingir
Em seguida, precisamos adicionar@EnableFeignClients à nossa classe principal:
@SpringBootApplication
@EnableFeignClients
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
Com esta anotação, habilitamos a varredura de componentes para interfaces que declaram serem clientes Feign.
Então,we declare a Feign client using the @FeignClient annotation:
@FeignClient(value = "jplaceholder", url = "https://jsonplaceholder.typicode.com/")
public interface JSONPlaceHolderClient {
@RequestMapping(method = RequestMethod.GET, value = "/posts")
List getPosts();
@RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
Post getPostById(@PathVariable("postId") Long postId);
}
Neste exemplo, configuramos um cliente para lerJSONPlaceHolder APIs.
O argumentovalue passado na nota sanitária@FeignClient é um nome de cliente arbitrário obrigatório, enquanto com o argumentourl, especificamos a URL base da API.
Além disso, como essa interface é um cliente Feign, podemos usar as anotações da Web Spring para declarar as APIs às quais queremos acessar.
4. Configuração
Agora, é muito importante entender queeach Feign client is composed of a set of customizable components.
Spring Cloud cria um novo conjunto padrão sob demanda para cada cliente nomeado usando a classeFeignClientsConfiguration que podemos personalizar conforme explicado na próxima seção.
A classe acima contém estes beans:
-
Decodificador -ResponseEntityDecoder, que envolveSpringDecoder, used para decodificar oResponse
-
Codificador -SpringEncoder, usado para codificar oRequestBody
-
Logger -Slf4jLogger é o logger padrão usado pelo Feign
-
Contrato -SpringMvcContract, que fornece processamento de anotação
-
Feign-Builder -HystrixFeign.Builder usado para construir os componentes
-
Cliente -LoadBalancerFeignClient ou cliente Feign padrão
4.1. Configuração Custom Beans
In the event that we want to customize one or more of these beans, podemos substituí-los usando uma classe@Configuration, que então adicionamos à anotaçãoFeignClient:
@FeignClient(value = "jplaceholder",
url = "https://jsonplaceholder.typicode.com/",
configuration = MyClientConfiguration.class)
@Configuration
public class MyClientConfiguration {
@Bean
public OkHttpClient client() {
return new OkHttpClient();
}
}
Neste exemplo, dizemos ao Feign para usarOkHttpClient em vez do padrão para suportar HTTP / 2.
O Feign oferece suporte a vários clientes para diferentes casos de uso, incluindoApacheHttpClient, que envia mais cabeçalhos com a solicitação - por exemplo,Content-Length, que alguns servidores esperam.
Para usar esses clientes, não se esqueça de adicionar as dependências necessárias ao nosso arquivopom.xml, por exemplo:
io.github.openfeign
feign-okhttp
io.github.openfeign
feign-httpclient
Podemos encontrar as versões mais recentes defeign-okhttpefeign-httpclient no Maven Central.
4.2. Configuração usando propriedades
Em vez de usar uma classe@Configuration,we can use application properties to configure Feign clients, conforme mostrado neste exemploapplication.yaml:
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
Com essa configuração, estamos definindo os tempos limite para 5 segundos e o nível do logger parabasic para cada cliente declarado no aplicativo.
Finalmente, podemos criar a configuração comdefault como o nome do cliente para configurar todos os objetos@FeignClient, ou podemos declarar o nome do cliente fingido para uma configuração:
feign:
client:
config:
jplaceholder:
No caso de termos@Configuration bean e propriedades de configuração, as propriedades de configuração substituirão os valores@Configuration.
5. Interceptores
Adicionar interceptores é outro recurso útil fornecido pelo Feign.
Os interceptores podem executar uma variedade de tarefas implícitas, da autenticação ao log, para cada solicitação / resposta HTTP.
Portanto, no snippet abaixo, vamos declarar um interceptor de solicitação que adiciona autenticação básica a cada solicitação:
@Bean
public RequestInterceptor requestInterceptor() {
return requestTemplate -> {
requestTemplate.header("user", username);
requestTemplate.header("password", password);
requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
};
}
Além disso, para adicionar o interceptor à cadeia de solicitação, precisamos apenas adicionar este bean à nossa classe@Configuration ou, como vimos anteriormente, declará-lo no arquivo de propriedades:
feign:
client:
config:
default:
requestInterceptors:
com.example.cloud.openfeign.JSONPlaceHolderInterceptor
6. Suporte Hystrix
Feign é compatível comHystrix, então, se o habilitamos,we can implement the fallback pattern.
Com o padrão de fallback, quando uma chamada de serviço remoto falha, em vez de gerar uma exceção, o consumidor do serviço executa um caminho de código alternativo para tentar executar a ação por outros meios.
Para atingir o objetivo, precisamos habilitar Hystrix adicionandofeign.hystrix.enabled=true no arquivo de propriedades.
Isso nos permite implementar métodos de fallback chamados quando o serviço falha:
@Component
public class JSONPlaceHolderFallback implements JSONPlaceHolderClient {
@Override
public List getPosts() {
return Collections.emptyList();
}
@Override
public Post getPostById(Long postId) {
return null;
}
}
Para informar ao Feign que os métodos de fallback foram fornecidos, também precisamos definir nossa classe de fallback na anotação@FeignClient:
@FeignClient(value = "jplaceholder",
url = "https://jsonplaceholder.typicode.com/",
fallback = JSONPlaceHolderFallback.class)
public interface JSONPlaceHolderClient {
// APIs
}
7. Exploração madeireira
Para cada cliente Feign, um criador de logs é criado por padrão.
Para habilitar o registro, devemos declará-lo no arquivoapplication.properties usando o nome do pacote das interfaces do cliente:
logging.level.com.example.cloud.openfeign.client: DEBUG
Ou, se quisermos habilitar o log apenas para um cliente em particular em um pacote, podemos usar o nome completo da classe:
logging.level.com.example.cloud.openfeign.client.JSONPlaceHolderClient: DEBUG
Observe que o log de Feign responde apenas ao nívelDEBUG.
OLogger.Level que podemos configurar por cliente indica quanto registrar:
@Configuration
public class ClientConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.BASIC;
}
}
Existem quatro níveis de registro para você escolher:
-
NONE - sem registro, que é o padrão
-
BASIC - registra apenas o método de solicitação, URL e status de resposta
-
HEADERS - registra as informações básicas junto com os cabeçalhos de solicitação e resposta
-
FULL - registra o corpo, cabeçalhos e metadados para solicitação e resposta
8. Manipulação de erros
O manipulador de erros padrão de Feign,ErrorDecoder.default, sempre lança umFeignException.
Agora, esse comportamento nem sempre é o mais útil. Então,to customize the Exception thrown, we can use a 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");
}
}
}
Então, como fizemos anteriormente, temos que substituir oErrorDecoder padrão adicionando um bean à classe@Configuration:
@Configuration
public class ClientConfiguration {
@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}
}
9. Conclusão
Neste artigo, discutimos o Spring Cloud OpenFeign e sua implementação em um aplicativo de amostra simples.
Além disso, vimos como configurar um cliente, como adicionar interceptores às nossas solicitações e como lidar com erros usandoHystrixeErrorDecoder.
Como de costume, todos os exemplos de código mostrados neste tutorial estão disponíveisover on GitHub.