Spring Cloud OpenFeign介绍

2023/05/13

1. 概述

在本教程中,我们将描述Spring Cloud OpenFeign—一个用于Spring Boot应用程序的声明式REST客户端。

Feign通过可插拔的注解支持(包括Feign注解和JAX-RS注解)使编写Web服务客户端变得更加容易。

此外,Spring Cloud添加了对Spring MVC注解的支持,并使用与Spring Web中使用的相同的HttpMessageConverters

使用Feign的一个好处是我们不必编写任何代码来调用服务,除了接口定义。

2. 依赖关系

首先,我们将首先创建一个Spring Boot Web项目并将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. Feign客户端

接下来,我们需要将@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注解中传递的value参数是一个强制的、任意的客户端名称,而使用url参数,我们指定API基本URL。

此外,由于此接口是一个Feign客户端,因此我们可以使用Spring Web注解来声明我们想要访问的API。

4. 配置

现在,了解每个Feign客户端都由一组可自定义的组件组成非常重要

Spring Cloud使用我们可以自定义的FeignClientsConfiguration类为每个命名客户端按需创建一个新的默认设置,如下一节所述。

上面的类包含这些bean:

  • Decoder:ResponseEntityDecoder,它包装了SpringDecoder,用于解码Response
  • Encoder:SpringEncoder用于对RequestBody进行编码
  • Logger:Slf4jLogger是Feign使用的默认记录器
  • Contract:SpringMvcContract,提供注解处理
  • Feign-Builder:HystrixFeign.Builder用于构建组件
  • Client:LoadBalancerFeignClient或默认的Feign客户端

4.1 自定义Bean配置

如果我们想要自定义一个或多个这些bean,我们可以通过创建一个Configuration类来覆盖它们,然后我们将其添加到FeignClient注解中:

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

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

在这个例子中,我们告诉Feign使用OkHttpClient而不是默认的客户端来支持HTTP/2。

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>

我们可以在Maven Central上找到最新版本的feign-okhttpfeign-httpclient

4.2 使用属性配置

我们可以使用应用程序属性来配置Feign客户端,而不是使用配置类,如application.yaml示例所示:

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

使用此配置,我们将应用程序中每个声明的客户端的超时设置为5秒,将Logger级别设置为basic。

最后,我们可以创建以default作为客户端名称的配置来配置所有@FeignClient对象,或者我们可以为配置声明feign客户端名称:

feign:
    client:
        config:
            jplaceholder:

如果我们同时拥有配置bean和配置属性,配置属性将覆盖配置bean的值。

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());
  	};
}

此外,要将拦截器添加到请求链中,我们只需将此bean添加到我们的Configuration类中,或者如我们之前所见,在属性文件中声明它:

feign:
    client:
        config:
            default:
                requestInterceptors:
                    cn.tuyucheng.taketoday.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知道已经提供了回退方法,我们还需要在@FeignClient注解中设置我们的回退类:

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

7. 日志记录

对于每个Feign客户端,默认情况下都会创建一个Logger。

要启用日志记录,我们应该使用客户端接口的包名称在application.propertie的文件中声明它:

logging.level.cn.tuyucheng.taketoday.cloud.openfeign.client=DEBUG

或者,如果我们只想为包中的一个特定客户端启用日志记录,我们可以使用完整的类名:

logging.level.cn.tuyucheng.taketoday.cloud.openfeign.client.JSONPlaceHolderClient=DEBUG

请注意,Feign日志记录仅响应DEBUG级别。

我们可以为每个客户端配置的Logger.Level指示记录多少

public class ClientConfiguration {

	@Bean
	Logger.Level feignLoggerLevel() {
		return Logger.Level.BASIC;
	}
}

有四种日志记录级别可供选择:

  • 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类添加一个bean来替换默认的ErrorDecoder:

public class ClientConfiguration {

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

9. 总结

在本文中,我们讨论了Spring Cloud OpenFeign及其在一个简单示例应用程序中的实现。

我们还了解了如何配置客户端、向我们的请求添加拦截器以及使用Hystrix和ErrorDecoder处理错误。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章