Open Feign 简单使用笔记

Open feign 可使远程调用 Http 接口更加遵循面向对象的思想, 使用 Open feign 调用远程API 就像调用本地接口一样

配置

使用版本
Spring boot 2.6.11 + Spring cloud alibaba 2021.0.4.0

依赖包

pom.xml
1
2
3
4
5
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.3</version>
</dependency>

注解

在 Spring boot 启动类上添加 @EnableFeignClients 注解

自定义配置

日志

Open Feign 的日志级别

级别 说明
NONE 不记录日志, 性能较佳
BASIC 记录请求方法, URL, 响应状态码, 执行时间
HEADERS 记录 BASIC 日志级别内容以及请求响应的 Header
FULL 记录请求, 响应的所有信息

Open Feign 输出日志的前提是在 Spring boot 的配置文件中 logging.level 中 Feign 接口的日志输出级别为 debug 以上

配置
全局配置
FeignConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.BASIC;
}
}
局部配置

@FeignClient注解中的 configuration 属性指定配置类或在 Spring boot 配置文件中对 feign.client.config.provider.logger-level 属性指定日志级别

feign.client.config.provider.logger-level 中的 provider 为服务名称

设置超时时间

全局配置
FeignConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import feign.Request;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;


@Configuration
public class FeignConfig {
@Bean
Request.Options options(){
return new Request.Options(100, TimeUnit.SECONDS, 1000, TimeUnit.SECONDS, true);
// 默认值为
// long connectTimeout = 10L
// TimeUnit connectTimeoutUnit = TimeUnit.SECONDS
// long readTimeout = 60L
// TimeUnit readTimeoutUnit = TimeUnit.SECONDS
// boolean followRedirects = true
}
}
局部配置

@FeignClient注解中的 configuration 属性指定配置类或在 Spring boot 配置文件中设置属性 feign.client.config.provider.connect-timeoutfeign.client.config.provider.read-timeout 的值

拦截器

Open Feign 的拦截器 需要实现 feign.RequestInterceptor 接口, 拦截器作用于请求之前

1
2
3
4
5
6
7
8
9
10
11
12
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;

@Component
public class FeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
System.out.println(requestTemplate);
}
}

手动注入可配置 Bean 或在 Spring boot 配置文件中设置属性 feign.client.config.provider.request-interceptors 的值

测试使用到的类

实体类

POJO.java
1
2
3
4
5
6
7
8
9
10
11
package com.example.consumer;

import lombok.Data;

@Data
public class POJO {
String id;
String name;
Integer age;
}

远程接口

Controller.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.example.consumer.POJO;
import com.fasterxml.jackson.databind.node.POJONode;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {

@GetMapping( "/test")
public String get() {
return hello + "1";
}

@PostMapping
public POJO post(@RequestBody POJO pojo){
return pojo;
}
}

Open Feign 声明式接口

FeignRemoteCall.java
1
2
3
4
5
6
7
8
9
10
11
12
13
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(name = "provider", path = "/")
public interface FeignRemoteCall {
@GetMapping( "/test")
public String get();

@PostMapping
public POJO post(@RequestBody POJO pojo);
}

@FeignClient 注解中常用属性

  • name (value) 属性 指服务名称
  • path 属性指 URI 前缀
  • url 属性 指远程主机地址

本地调用

FeignController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("feign")
public class FeignController {
private final FeignRemoteCall feignRemoteCall;

public FeignController(FeignRemoteCall feignRemoteCall) {
this.feignRemoteCall = feignRemoteCall;
}

@GetMapping("/get")
public String get(){
return feignRemoteCall.get();
}

@GetMapping("/post")
public POJO post(){
POJO pojo = new POJO();
pojo.setName("username");
pojo.setId("id001");
pojo.setAge(21);
return feignRemoteCall.post(pojo);
}
}

注解

Spring MVC 注解

@FeignClient 类中默认可以使用 @RequestMapping, @GetMapping, @PathVariable 等 Spring MVC 中的注解, 注解意义与 Spring MVC 中相同

Open Feign 注解

配置

全局配置
FeignController.java
1
2
3
4
5
6
7
8
9
10
11
12
import feign.Contract;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class FeignConfig {
@Bean
Contract contract(){
return new Contract.Default();
}
}
局部配置

@FeignClient注解中的 configuration 属性指定配置类或在 Spring boot 配置文件中设置属性 feign.client.config.provider.contract 值为 feign.Contract.Default

映射关系

@RequestMapping -> @RequestLine
@PathVariable -> @Param

JAX-RS 注解