一、为什么要使用Feign
Feign是一个声明式的web service客户端,本质上它和原生的URLConnection、HTTP Client、RestTemplate等HTTP工具是一样的,但是在使用方式上具有很大的不同,变得非常简洁。
使用Feign只需要创建一个接口,并在接口上加上@FeignClient
注解即可,然后在其中声明方法和具体的调用URL,当我们在外部调用这些方法的时候,底层就是对声明的URL进行访问。
Feign是一种声明式的,模板化的HTTP客户端,可以做到使用HTTP请求访问远程服务就像在调用本地方法一样,开发者完全感觉不到这是在调用远程方法,更感知不到是在发起HTTP请求。
二、入门示例
我们在start.spring.io
上一键生成一个自带Feign依赖的项目:

然后在启动类上加上@EnableFeignClients
注解,使得项目启动的时候,去扫描所有@FeignClient
的类。
然后我们新建一个Feign接口:
@FeignClient(name = "github-client", url = "https://api.github.com")
public interface GithubFeignService {
@RequestMapping(value = "/search/repositories", method = RequestMethod.GET)
String searchRepo(@RequestParam("q") String queryString);
}
当其它方法调用该接口的这个方法时,其实就是发起一个如下的HTTP请求:
https://api.github.com/search/repositories?q=xxx
并且标注返回内容是String类型,那么我们下面就来调用这个方法:
@RestController
public class GitHubController {
@Autowired
private GithubFeignService githubFeignService;
@GetMapping(value = "/search/github")
public String searchHitHubRepoByString(@RequestParam("str") String queryString){
return githubFeignService.searchRepo(queryString);
}
}
当启动项目后,我们访问http://localhost:8080/search/github?str=spring-cloud-dubbo
就能得到如下的返回内容:

看样子真的是从github的接口调用并返回了信息,我们直接调用github接口验证下呢:

看来确实没有问题,简单实例到此结束。
三、工作原理
- 当项目启动时,因为启动类上有
@EnableFeignClients
注解,因此会扫描项目下所有标注了@FeignClient
注解的类,并将它们注入到Spring容器中; - 当某个Feign接口方法被调用的时候,通过动态代理来生成具体的RequestTemplate对象,并封装了HTTP请求需要的全部信息;
- RequestTemplate对象会被进一步封装成Request对象,交给真正的HTTP客户端类去处理,比如URLConnection、HTTP Client、RestTemplate等,其默认是使用原生的URLConnection,当然可以通过配置的方式来进行替换,这个后面再进行讲解。
四、核心配置
4.1 开启日志
-
先在配置文件
application.properties
中增加如下配置logging.level.com.example.feigndemo.feignService.GithubFeignService=debug
当然,以后如果FeignService多了,可以使用通配符。
-
然后增加如下配置类
@Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel(){ return Logger.Level.FULL; } }
其中,日志级别有如下几种:
- NONE,不记录,默认选项;
- BASIC,仅记录请求方法和URL,还有响应状态代码和执行时间;
- HEADERS,记录基本信息以及请求和响应头信息;
- FULL,记录全部信息;
-
最后在FeignService接口上增加配置的使用
@FeignClient(name = "github-client", url = "https://api.github.com", configuration = FeignConfig.class) public interface GithubFeignService { @RequestMapping(value = "/search/repositories", method = RequestMethod.GET) String searchRepo(@RequestParam("q") String queryString); }
此时再启动项目,并访问就会发现控制台有Feign的日志输出了。

4.2 配置超时时间
feign.client.config.default.connectTimeout=5
feign.client.config.default.readTimeout=5000
我们故意将connectTimeout设置的极短,再次启动项目,访问后发现服务端报错:

4.3 开启自定义配置
-
对单个FeignService开启自定义配置
可以在配置文件中指定FeignService的名称来进行配置:
feign.client.config.yourFeignName.connectTimeout=5000 feign.client.config.yourFeignName.readTimeout=5000 ...
当然,yourFeignName可以支持通配符。
-
对所有的FeignService开启自定义配置
可以先新建一个配置类
DefaultFeignConfig
.java,然后在启动类上加上这个配置类:@SpringBootApplication @EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class) public class FeignDemoApplication { public static void main(String[] args) { SpringApplication.run(FeignDemoApplication.class, args); } }
除了写配置类,还可以在配置文件中使用default来代替特定的yourFeignName,参考4.3的配置内容。
五、整合Eureka使用
在上一篇中介绍了Eureka的基本使用,可以参考《Eureka注册中心入门》,给我们当前Feign的例子加上Eureka客户端的能力。
5.1 pom中引入eureka-client依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
5.2 启动类标注eureka-client
@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class FeignDemoApplication {
public static void main(String[] args) {
SpringApplication.run(FeignDemoApplication.class, args);
}
}
5.3 增加eureka-client的配置
server.port=8090
# 当前应用名称
spring.application.name=eureka-feign-client
# eureka注册中心地址
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8761/eureka/
5.3 创建Feign接口
@FeignClient(name="eureka-client", configuration = FeignConfig.class)
public interface EurekaClientService {
@RequestMapping(value="/getHello", method = RequestMethod.GET)
String getHello();
}
此处name属性就是需要调用的服务的名称。
5.4 创建Rest接口
@RestController
public class EurekaClientController {
@Autowired
private EurekaClientService eurekaClientService;
@GetMapping(value = "/getHello")
public String getHello(){
return eurekaClientService.getHello();
}
}
5.5 启动服务
依次启动eureka-server、eureka-client1、eureka-client2、eureka-feign-client服务。

在浏览器中输入http://localhost:8090/getHello
,请求就能通过eureka-feign-client转发到eureka-client的服务上,得到返回信息。
网友评论