基本介绍
Feign 是Spring Cloud Netflix项目中的HTTP服务客户端,支持ReST准则和SOAP协议,实现了负载均衡和 Rest 调用的开源框架,封装了Ribbon和RestTemplate, 实现了WebService的面向接口编程,旨在降低http调用的复杂度,减少调用开销和简化代码。
为了方便使用,SpringCloud开发OpenFeign作为第二代客户端集成了Ribbon或LoadBalancer,在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。
组件支持
简单应用
- 注解
| Annotation | Interface Target | Usage | 
|---|---|---|
| @RequestLine | Method | 定义请求,支持表达式值映射, {expression}解析为@Param对应变量 | 
| @Param | Parameter | 定义模板变量,参数名对应注解提供的名称 | 
| @Headers | Method, Type | 定义请求头 支持表达式值映射, {expression}解析为@Param对应变量 | 
| @QueryMap/@SpringQueryMap | Parameter | 定义请求参数Map,后者为OpenFeign提供支持Spring的Map注解 | 
| @HeaderMap | Parameter | 定义请求头Map,将扩展到请求头 | 
| @Body | Method | 定义一个请求体,支持表达式值映射,如xml、json表达式 | 
- Feign客户端
声明式接口调用 Feign通过使用Java接口的方式,让我们可以轻松地声明需要调用的远程接口。无需编写繁琐的HTTP请求代码,我们只需定义一个接口,并在方法上添加注解来标识请求的URL、HTTP方法、请求参数等信息。Feign集成了负载均衡的功能,可以与服务注册中心(如Eureka)进行集成,自动实现服务的发现与负载均衡。这意味着我们可以通过Feign调用任何可用的服务,而无需关心具体的服务实例。
@FeignClient(contextId = "remoteUserService", value = "cloud-system", fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService {
    @GetMapping(value = "/user/getUserInfo",)
    Response<List<UserInfo>> getUserInfo(@RequestParam("userId") int userId);
    @RequestMapping(value = "/user/addUserInfo", method =  RequestMethod.POST)
    Response<String> addUserInfo(@RequestBody("userInfo") UserInfo userInfo);
}- 拦截器
Feign提供了很多配置选项,可以满足我们对接口调用的各种需求。我们可以通过自定义Feign的配置类来进行定制,例如修改请求头、添加拦截器等。
//请求拦截器
public class FeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        Map<String, String> headers = getHeaders();
        headers.forEach(template::header);
    }
}
//响应拦截器
public class CustomResponseInterceptor implements ResponseInterceptor {
    @Override
    public void interceptResponse(Response response) {
        if (response.status() == 401) {
            throw new UnauthorizedException();
        }
    }
}
/********************************************************************/
// 局部拦截器注册
@FeignClient(name = "gateway", configuration = FeignInterceptor.class, fallbackFactory = RemoteUserFallbackFactory.class)
// 全局拦截器注册
@Configuration 
public class FeignConfig {
    @Bean
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("fox", "123456");
    }
}- 异常处理机制
@Slf4j
public class OpenFeignErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        log.error("feign client error,response is {}:",response);
        return new BusinessException("Feign client 调用异常");
    }
}- 超时与重试机制
在网络通信中,不可避免地会出现请求超时或异常的情况。Feign提供了超时和重试的机制,允许我们设置请求的超时时间,并在请求失败时进行重试,提高了调用的可靠性。
public class MyRetryer implements Retryer {
    @Override
    public void continueOrPropagate(RetryableException e) {
        throw e;
    }
    @Override
    public Retryer clone() {
        return new Default(100, TimeUnit.SECONDS.toMillis(1), 5);
        // period:周期,重试间隔时间
        //maxPeriod:最大周期,重试间隔时间按照一定的规则逐渐增大,但不能超过最大周期
        //maxAttempts:最大尝试次数,重试次数
    }
}
总结
Feign作为一个简单易用的HTTP客户端工具,为我们的服务间通信提供了便利。通过其声明式的接口调用、自动序列化与反序列化、负载均衡与服务发现、超时与重试机制以及易于扩展和定制等特性,我们可以更加轻松地实现接口调用的功能。