Feign 简介
Spring Cloud的Feign支持的一个中心概念就是命名客户端.Feign客户端使用@FeignClient注册组合成组件,按需调用远程服务器. Spring Cloud使用FeignClientsConfiguration创建一个新的集合作为每个命名客户端的ApplicationContext(应用上下文), 包含feign.Decoder,feign.Encoder和feign.Contract.
你可以使用 Jersey 和 CXF 这些来写一个 Rest 或 SOAP 服务的java客服端。你也可以直接使用 Apache HttpClient 来实现。但是 Feign 的目的是尽量的减少资源和代码来实现和 HTTP API 的连接。通过自定义的编码解码器以及错误处理,你可以编写任何基于文本的 HTTP API。
Feign 通过注解注入一个模板化请求进行工作。只需在发送之前关闭它,参数就可以被直接的运用到模板中。然而这也限制了 Feign,只支持文本形式的API,它在响应请求等方面极大的简化了系统。同时,它也是十分容易进行单元测试的。
Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。
Spring Cloud Feign是基于Netflix Feign实现,整合了Spring Cloud Riggon与Spring Cloud Hystrix,出了提供这两者的强大功能外,他还提供了一种声明式的Web服务客户端 定义方式。
在使用Spring Cloud Ribbon时,通常都会利用它对RestTemplate的请求拦截来实现对服务的调用,而RestTemplate已经实现了对HTTP请求的封装处理,形成了一套模板化的调用方法。
快速使用
添加对feign的依赖:
1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
在主类使用注解开启Feign的功能:
1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public
class
OwlBookstoreWebApiApplication {
public
static
void
main(String[] args) {
SpringApplication.run(OwlBookstoreWebApiApplication.
class
, args);
}
}
修改配置文件:
1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public
class
OwlBookstoreWebApiApplication {
public
static
void
main(String[] args) {
SpringApplication.run(OwlBookstoreWebApiApplication.
class
, args);
}
}
接着
接着,创建调用接口 ,使用注解来消费服务;该接口及对应的FallbackFactory类最好位于包feign下,便于管理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import
org.springframework.cloud.netflix.feign.FeignClient;
import
org.springframework.web.bind.annotation.PathVariable;
import
org.springframework.web.bind.annotation.RequestMapping;
import
org.springframework.web.bind.annotation.RequestMethod;
import
cn.net.bysoft.owl.bookstore.facade.user.entity.User;
import
cn.net.bysoft.owl.bookstore.web.api.fallback.UserServiceFallbackFactory;
@FeignClient
(value =
"/DataSource"
, fallbackFactory = UserServiceFallbackFactory.
class
)
public
interface
UserService {
@RequestMapping
(value =
"https://my.oschina.net/users/{email}/"
, method = RequestMethod.GET)
Boolean isExistsByEmail(
@PathVariable
(
"email"
) String email);
@RequestMapping
(value =
"https://my.oschina.net/users/{id}"
, method = RequestMethod.GET)
User findById(
@PathVariable
(
"id"
) Long id);
}
接口中声明的方法的参数与返回值,要与服务提供的方法一致。
Feign自动开启了Ribbon中的负载均衡和hystrix断路器,要使用断路器先需要开启断路器:
1
2
3
4
5
6
7
8
feign:
hystrix:
enabled:
true
compression:
request:
enabled:
true
response:
enabled:
true
在Feign中使用fallbackFactory来降级服务,使用该方式可以同时处理服务抛出的异常,创建一个UserServiceFallbackFactory类:
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
28
29
30
import
org.springframework.stereotype.Component;
import
cn.net.bysoft.owl.bookstore.facade.user.entity.User;
import
cn.net.bysoft.owl.bookstore.web.api.service.UserService;
import
feign.hystrix.FallbackFactory;
@Component
public
class
UserServiceFallbackFactory
implements
FallbackFactory<UserService> {
@Override
public
UserService create(Throwable cause) {
return
new
UserService() {
@Override
public
Boolean isExistsByEmail(String email) {
system.out.println(cause.getmessage());
return
false
;
}
@Override
public
User findById(Long id) {
cause.printStackTrace();
System.out.println(cause.getMessage());
return
null
;
}
};
}
}
Ribbon配置
全局配置的方法很简单:
1
2
ribbon.ConnectTimeout=
500
ribbon.ReadTimeout=
5000