(1)什么是Feign?
1、Rest是Netflix公司开源的轻量级Rest客户端,使用Feign可以非常轻便简单的实现Http客户端,只需要定义一个接口,然后在接口上添加注解@FeignClient即可;SpringCloud对Feign进行了封装,并且是默认集成了Ribbon,实现了客户端负载均衡调用的;简而言之,我们之前是通过RestTemplate+Ribbon的方式进行负载均衡和调用Rest服务的,现如今我们可以利用新组件Feign通过接口的方式来进行调用rest服务;
2、微服务的调用就有两种方式:
1. 通过微服务名称,获得服务的调用地址
2. 通过接口+注解,获得服务的调用–Feign(为业界程序员提出,并且是面向接口编程),类似于在Mapper接口上使用@Mapper注解进行标识,而使用Feign也是只需要在接口上添加注解@FeignClient,即可完成服务提供方的接口绑定,简化了在使用SpringCloud Ribbon时自行封装服务调用客户端的开发量;
(2)Feign的工作原理
1、启动类上添加@EnableFeignClient注解,Spring会扫描标记了@FeignClient注解的接口,并生成此接口的代理对象;
2、@FeignClient(“服务名称”),即指定了服务提供者的服务名称,让Feign可以从Eureka注册中心获得到服务列表(即我们注册到EurekaServer中的所有服务),并通过负载均衡算法进行服务调用;
3、在接口方法中我们依然使用注解RequestMapping(value="/product/list",method = RequestMethod.GET),指定调用的URL,Feign会根据URL进行远程调用;
(3)在实际开发中,我们如何使用Feign进行开发?
1、在pom文件中添加上相应的依赖,表名开启Feign:
<!-- 与此同时我们添加上开启feign的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
2、添加一个接口,里面添加上相应的方法,并且添加上@FeignClient注解,里面加上服务名称;
import java.util.List;
/**
* 因为我们feign是基于接口的调用,所以我们这里使用接口来进行操作
* 故我们使用以下注解来标识使用哪个服务,
* 以下就是调用MICROSERVICE-PRODUCT服务中的/product/list 、
* /product/get/{id}、/product/add 接 口
*/
@FeignClient(value = "MICROSERVICE-PRODUCT")
@Service
public interface ProductClientService {
//在接口里面添加相应的方法
@RequestMapping(value = "/product/get/{id}", method = RequestMethod.GET)
Product get(Long id);
@RequestMapping(value = "/product/list", method = RequestMethod.GET)
List<Product> list();
@RequestMapping(value = "/product/add", method = RequestMethod.POST)
boolean add(Product product);
}
3、然后在启动类上添加注解@EnableFeignClients(basePackages =“com.mengxuegu.springcloud”),如下:
//这里我们需要加上一个Feign的注解:
// 其会帮我们扫描指定包下加了@FeignClients注解的接口,并生成此接口的代理对象
@EnableFeignClients(basePackages ="com.mengxuegu.springcloud")
//我们这里需要标识其为Eureka客户端
@EnableEurekaClient
@SpringBootApplication
public class ProductConsumer_80_Feign {
public static void main(String[] args) {
SpringApplication.run(ProductConsumer_80_Feign.class, args);
}
}
4、最后我们在控制层上对我们的接口进行注入,并且直接使用接口对象来调用服务中的方法(之前我们是使用RestTemplate来进行调用,并且还需要加上一长串的路径前缀);
@RestController
//这里将我们之前使用服务名调用服务提供着的类名进行更改,改为“ProductController_Feign”
public class ProductController_Feign {
/**
* 因为我们在config配置类中添加了@LoadBalance注解,所以我们可以直接通过restTemplate调用,实现负载均衡
* //并且可以使用yml文件中的服务名(就是下面我们列举出的服务名)对其此处的IP地址继续替换
* spring:
* application:
* name: microservice-product
* // private static final String REST_URL_PREFIX = "http://localhost:8001";
*/
private static final String REST_URL_PREFIX = "http://microservice-product";
@Autowired
private RestTemplate restTemplate;
//刚才我们也讲了,因为我们feign是需要用到接口来进行服务的调用,故我们这里把接口对象注入
@Autowired
ProductClientService productClientService;
@RequestMapping(value = "/consumer/product/add")
public boolean add(Product product) {
// return restTemplate.postForObject(REST_URL_PREFIX + "/product/add", product, Boolean.class);
//这里的话我们就可以直接去使用service对象来调用接口中的add方法,而不用使用以上的restTemplate来调用服务
return productClientService.add(product);
}
@RequestMapping(value = "/consumer/product/get/{id}")
public Product get(@PathVariable("id") Long id) {
// return restTemplate.getForObject(REST_URL_PREFIX + "/product/get/" + id, Product.class);
return productClientService.get(id);
}
@RequestMapping(value = "/consumer/product/list")
public List<Product> list() {
// return restTemplate.getForObject(REST_URL_PREFIX + "/product/list", List.class);
return productClientService.list();
}
}
很明显,之前我们使用RestTemplate+Ribbon进行Rest服务调用特别繁琐,得加上很长的Url地址,并且参数,以及类型,万一写错程序就炸了!故我们采用Feign使用接口对象进行服务调用使用起来特别清爽~~~