声明式服务调用Feign

之前我们通过RestTemplate调用REST服务,代码是这样的:

    @HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
    public Item queryItemById(Long id) {
        String serviceId = "xushu-microservice-item";
        return this.restTemplate.getForObject("http://" + serviceId + "/item/" + id, Item.class);
    }

虽然使用了Ribbon和Hystrix可以实现负载均衡和容错处理,但是硬编码会在业务繁杂时显得非常冗余。所以,我们可以用更优雅的Feign来实现这个功能。

Feign简介

Feign时Netflix开发的声明式、模块化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket。Feign可以帮助我们更便捷、优雅的调用HTTP API。

在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加相关的注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。

Spring Cloud对Feign进行了增强,时Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign使用更加方便。

快速入门

在这里,我们在订单微服务中增加Feign的支持。

首先,我们导入依赖:

                <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

然后,我们创建一个ItemFeignClient接口

package com.example.order.feign;


import com.example.order.pojo.Item;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(value = "xushu-microservice-item")// 申明这是一个Feign客户端,并且指明服务id
public interface ItemFeignClient {

    // 这里定义了类似于SpringMVC用法的方法,就可以进行RESTful的调用了
    @RequestMapping(value = "/item/{id}", method = RequestMethod.GET)
    public Item queryItemById(@PathVariable("id") Long id);
}

然后改造ItemService


然后,在启动类中添加@EnableFeignClients注解


后面测试,发现一切正常。但是到底是为什么呢?

流程如下:

  • 1.由于我们在入口添加了@EnableFeignClients注解,Spring启动后会自动扫描标注了@FeignClient注解的接口,然后生成代理类。
  • 2.我们在@FeignClient接口中指定了value,其实就是制订了在Eureka中的服务名称。
  • 3.在FeignClient中的定义方法以及使用了SpringMVC的注解,Feign就会根据注解中的内容生成对应的URL,然后基于Ribbon的负载均衡去调用REST服务(而以前需要使用RestTemplate)。
    ~~~~a)为什么使用SpringMVC的注解?
    ~~~~~~~~i)其实,Feign是有自己的注解的,是因为SpringCloud对Feign做了增强,兼容了SpringMVC的注解,使得我们的学习成本更低。

    ~~~~~~~~ii)专业的介绍是这样的:

推荐阅读更多精彩内容