Feign是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。
在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。
Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。
Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。
Spring Cloud Feign具备可插拔的注解支持,支持Feign注解、JAX-RS注解和Spring MVC的注解。
要想使用Feign,首先要做的自然就是引入依赖了,我们在cargoAccesser模块中的pom.xml添加如下的依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
<version>2.0.4.RELEASEversion>
dependency>
导入依赖到我们的项目中,就可以着手使用Feign客户端了。
我们在cargoAccesser模块下src/main/java下新建一个名为feign的包,cargoAccesser这个模块的微服务依赖于microservicefirst模块提供的app-cargo微服务。先前我们使用的是Rest模板的方式请求app-cargo的微服务,现在我们将使用一种更加优雅的方式。
在刚刚建立的feign包下新建一个接口,命名为CargoFeignClient。在接口名上加上@FeignClient(value = “app-cargo”)注解,声明这是一个FeignClient,并且服务地址为app-cargo。
在接口中声明一个queryCargoById方法,并且在方法上加上@RequestMapping(value="/cargo/{id}",method = RequestMethod.GET)注解,标记了API中对应接口方法的请求方式以及URL。
Feign客户端接口完整代码如下
package feign;
import entity.Cargo;
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 = "app-cargo")//声明这是一个FeignClient,服务地址为app-cargo
public interface CargoFeignClient {
@RequestMapping(value = "/cargo/{id}", method = RequestMethod.GET)
//没错,就是和MVC注解一样!这个注解由@RequestLine增强而来。声明请求路径,方法为GET
Cargo queryCargoById(@PathVariable("id") Long id);
}
原先我们在cargoAccesser模块中的CargoService中写了使用RestTemplate调用app-cargo的方法,之前我们的写法是这样的
String cargoUrl = "http://app-cargo/cargo/{id}";
Cargo cargo = this.restTemplate.getForObject(cargoUrl,Cargo.class,id);
在我们使用了FeignClient之后,我们可以用更加优雅的方式来实现这一功能。我们删掉原来这两行代码,在这个Service中新增一个CargoFeignClient成员变量,并开启自动注入。在执行调用请求的方法中,新增一行代码
Cargo cargo = cargoFeignClient.queryCargoById(id);
这样可以通过我们刚刚声明的FeignClient来实现调用,在IDEA中声明CargoFeignClient的自动注入会出现红线,但编译没有出现问题,我们可以通过注解忽略报错提示。
最后,我们在启动类上开启FeignClient,并标记扫描的包就可以启动cargoAccesser模块了。在启动类上添加如下的注解
@EnableFeignClients(basePackages ="feign")//启动Feign服务,指定扫描的包
启动服务,访问http://localhost:8095/cargoList/123,发现能正常调用app-cargo微服务。这样我们就完成了FeignClient的声明式API调用了。
在上一节我们使用了Hystrix阻止了服务雪崩,但是在每一个Service对应的方法下都要声明一个Fallback方法,这样我们的代码结构就会受到影响。本文开头引用的Feign简介部分提到,Feign整合了Hystrix,那么使用FeignClient也是可以让我们的熔断变得更加优雅的,具体实现步骤如下
我们在模块下新建一个fallback包,在包下新建一个名为CargoServiceFallback的类,类上需要加上@Component注解,表示这个类是一个组件,这个类要实现我们声明的FeignClient接口,这个类就用来放调用app-cargo出错时的回调方法,完整代码如下
package fallback;
import entity.Cargo;
import feign.CargoFeignClient;
import org.springframework.stereotype.Component;
@Component
public class CargoServiceFallback implements CargoFeignClient {
@Override
public Cargo queryCargoById(Long id) {
return new Cargo(id,"请求不到name","请求不到price");
}
}
代码中的queryCargoById方法的内容与我们之前使用的fallback方法内容基本一致,就不做赘述了。
我们已经准备好对app-cargo服务的容错方法了,接下来我们要把刚刚做的事情让SpringBoot框架扫描到。
由于Feign是集成的Hystrix,因此要在yml文件中配置一下,告诉SpringBoot启动Feign的Hystrix。在yml中添加如下配置信息
feign:
hystrix:
enabled: true #启动熔断容错处理
然后在启动类上修改SpringBoot的包扫描路径,在其中添加一个fallback包就可以了
@SpringBootApplication(scanBasePackages={
"controller","entity","service","fallback"})
我们注释掉CargoService类queryCargoById上的@HystrixCommand注解,这个方法不再被我们添加的Hystrix组件管理了,而是被Feign集成的Hystrix组件控制。
我们启动app-cargo-list微服务,并且停止app-cargo微服务,访问http://localhost:8095/cargoList/123,发现Hystrix依然能够正常工作。我们的目标实现了!
本文引用了Feign简介与简单应用中的部分内容
引用原文作者为 cakincqm
如有侵权,请联系我处理