https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/
@GetMapping("/album/{id}")
public Album getById(@PathVariable int id){
//调用唱片微服务获取
String url="http://musicstore-albumservice/album/"+id;
Album album=restTemplate.getForObject(url,Album.class);
return album;
}
由上述的代码可以看出,我们以字符串拼接的方式构造URL的,该URL只有一个参数。但是,在现实
中,URL中往往含有多个参数。这时候我们如果还用这种方式构造URL,那么就会非常痛苦。那应该如何解决?
Feign是一个声明式 Web 服务客户端。它使编写 Web 服务客户端更容易。要使用 Feign,创建一个接口并对其进行注解。它具有可插入的注释支持,包括 Feign 注释和 JAX-RS 注释。Feign 还支持可插拔的编码器和解码器。Spring Cloud 添加了对 Spring MVC 注解的支持,并支持使用HttpMessageConvertersSpring Web 中默认使用的注释。Spring Cloud 集成了 Eureka、Spring Cloud CircuitBreaker 以及 Spring Cloud LoadBalancer,在使用 Feign 时提供负载均衡的 http 客户端。
声明式调用就像调用本地方法一样调用远程方法,无感知远程HTTP请求。
SpringCloud的声明式调用,可以做到使用HTTP请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法。更感知不到这是一个HTTP请求。
它像Dubbo一样,consumer直接调用接口方法调用provider,而不需要通过常规的Http Client构造请求再解析返回数据。
4.它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class);
}
}
在订单服务中创建接口ProductFeignClient用于调用远程的Product服务
//指定要调用的微服务的名称
@FeignClient(name = "product-service")
public interface ProductFeignClient {
@GetMapping("/product")
public String queryProduct();
}
定义各参数绑定时,@PathVariable、@RequestParam、@RequestHeader等可以指定参数属性,在Feign中绑定参数必须通过value属性来指明具体的参数名,不然会抛出异常。
@FeignClient:注解通过name指定需要调用的微服务的名称,用于创建Ribbon的负载均衡器。所以Ribbon会把product-service解析为注册中心的服务。
修改订单控制器OrderController,注入ProductService,实现服务调用
@RestController
public class IndexController {
@Autowired
private ProductFeignClient productFeignClient;
@RequestMapping("/order")
public String order(){
return productFeignClient.queryProduct();
}
}
在浏览器中可以看到正确的调用结果 ,同时开启多个提供者
1、 启动类添加@EnableFeignClients注解,Spring会扫描标记了@FeignClient注解的接口,并生成此接口的代理对象
2、 @FeignClient(value = “product-service”)即指定了要调用的服务名称,Feign会从注册中心获取product-service服务列表,并通过负载均衡算法进行服务调用。
3、在接口方法 中使用注解@GetMapping(“/product”)"),指定调用的url,Feign将根据url进行远程调用。
Ribbon是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。它可以 在客户端 配置RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。
Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写客户端变得非常容易.
Feign中本身已经集成了Ribbon依赖和自动配置,因此我们不需要额外引入依赖,也不需要再注册RestTemplate 对象。分别以8081和8282启动两个产品服务productService,可以看到结果还是使用ribbon的轮询策略进行服务调用,实现负载均衡。
总结:从SpringCloud Edgware开始,Feign支持使用属性自定义Feign。对于一个指定名称的FeignClient可以设置名称,连接超时时间,日志级别,请求拦截等等。
Feign传参确保消费者和提供者的参数列表一致 包括返回值 方法签名要一致
1. 通过URL传参数,GET请求,参数列表使用@PathVariable(“”)
2. 如果是GET请求,每个基本参数必须加@RequestParam(“”)
3. 如果是POST请求,而且是对象集合等参数,必须加@Requestbody 或者@RequestParam
@GetMapping("/detail/{id}")
public String detail(@PathVariable("id")Integer id){
return "商品详情,编号:"+id+"....8081";
}
@GetMapping("/add")
public String add(Integer id,String name){
return "增加商品信息为:id="+id+",name="+name+"...8081";
}
@GetMapping("/detail/{id}")
String detail(@PathVariable("id")Integer id);
@GetMapping("/add")
String add(@RequestParam("id") Integer id,@RequestParam("name") String name);
feign:
client:
config: # 因为一个应用中 feign的客户端可以有很多 这里需要写具体的一个feign的名称
default: # 写成default就是所有的客户端都通用
connectTimeout: 5000
readTimeout: 5000 # 默认的超时 5s
从前面的测试中我们可以看出,没有任何关于远程调用的日志输出,如请头,参数
Feign提供了日志打印功能,我们可以通过配置来调整日志级别,从而揭开Feign中Http请求的所有细节
NONE 默认的,不显示日志
BASE 仅记录请求方法,URL ,响应状态码及执行时间
HEADERS 在BASE之上增加了请求和响应头的信息
FULL 在HEADERS之上增加了请求和响应的正文及无数据
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLogger() {
return Logger.Level.FULL;
}
}
feign:
client:
config: # 因为一个应用中 feign的客户端可以有很多 这里需要写具体的一个feign的名称
default: # 写成default就是所有的客户端都通用
connectTimeout: 5000
readTimeout: 5000 # 默认的超时 5s
loggerLevel: HEADERS
logging:
level:
com.powernode.feign.ProductFeign: debug # 默认只支持debug级别
一旦通过ProductFeign调用远程方法,控制台会打印日志信息