Feign简介
Feign是声明式的web service客户端,它让微服务的调用变得更简单了,类似Controller调用service。SpringCloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。
只需要创建一个接口,然后添加注解即可!
Feign说明
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,主要是社区、大家都习惯面向接口编程,这个是很多开发人员的规范。
调用微服务访问的两种方法
1.微服务名字【ribbon】
2.接口和注解【feign】
Feign能做什么
- Feign意在使编写Java Http客户端变得更容易
- 在实际的开发当中,由于对服务依赖的调用不止一处,这就导致一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。
- Feign就在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它,(类似于以前Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可)即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量。
Feign具有如下特性
支持可插拔的HTTP编码器和解码器;
支持Hystrix和它的Fallback;
支持Ribbon的负载均衡;
支持HTTP请求和响应的压缩。
有点像我们springmvc模式的Controller层的RequestMapping映射。这Feign是用@FeignClient来映射服务的。
Feign的使用
首选根据父工程创建feign子工程
改子模块也是做负载均衡,所以直接拷贝springcloud-consumer-dept-8082
移出主启动类中的ribbon自定义
package org.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
@EnableDiscoveryClient
public class DeptConsumer_8090 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_8090.class, args);
}
}
feign是根据 接口调用所以添加接口
类似与Dubbo的服务调用接口,添加@FeignClient注解就会自动扫描
Dubbo和Feign区别
package org.springcloud.service;
import java.util.List;
import org.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@FeignClient(name = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
@GetMapping("/dept/queryById/{deptno}")
public Dept queryById(@PathVariable("deptno") Long deptno);
@GetMapping("/dept/queryList")
public List<Dept> queryList();
}
@FeignClient常用属性
name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
url: url一般用于调试,可以手动指定@FeignClient调用的地址
decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
path: 定义当前FeignClient的统一前缀,当我们项目中配置了server.context-path,server.servlet-path时使用
修改springcloud-consumer-dept-feign中的DeptConsumerController访问方式,以注入接口访问
package org.springcloud.controller;
import java.util.List;
import org.springcloud.pojo.Dept;
import org.springcloud.service.DeptClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class DeptConsumerController {
// 在这边没有service接口,
// 理解:消费者 应不应该有service 结果是不需要执行访问就好
// 因为需要restful 风格 肯定有RestTempLate spring会提供模板,供我们调用使用
/**
* 注入RestTemplate bean 参数 url,request请求:一般用map,class<T>,
*/
@Autowired
private RestTemplate restTemplate;// 提供多种便捷访问远程http服务的方法,简单的restful服务模板
private static final String REST_URL = "http://SPRINGCLOUD-PROVIDER-DEPT";
/**
* 通过api中的接口,在feign自动自动注入到feign服务调用方
*/
@Autowired
private DeptClientService deptClientService;
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return this.deptClientService.queryById(id);
}
@RequestMapping("/consumer/dept/add")
public Boolean add(Dept dept) {
System.err.println("消费者:" + dept);
return this.deptClientService.addDept(dept);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list() {
return this.deptClientService.queryList();
}
}
Ribbon和Feign区别
feign与ribbon调用方式,feign更加java化接口方式,以接口注解方式调用,ribbon通过SPRINGCLOUD-PROVIDER-DEPT服务名以及RestTemplate进行调用,feign默认集成了ribbon
与Ribbon一样在起到类中加eable+feign…
package org.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
@EnableDiscoveryClient
@EnableFeignClients(basePackages = { "org.springcloud" }) // 添加启动Feign注解,选择需要扫描的包,与Dubbo十分相似
@ComponentScan("org.springcloud") // 扫描包路径下注解
public class DeptConsumer_8090 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_8090.class, args);
}
}
启动feign服务调用 访问http://localhost:8090/consumer/dept/list