1.简介
1.1 概述
Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same
HttpMessageConverters
used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka, as well as Spring Cloud LoadBalancer to provide a load-balanced http client when using Feign.
Feign是声明性Web服务客户端。它使编写Web服务客户端更加容易。要使用Feign,请创建一个接口并对其进行注释。它具有可插入注释支持,包括Feign注释和JAX-RS注释。 Feign还支持可插拔编码器和解码器。 Spring Cloud添加了对Spring MVC注释的支持,并支持使用Spring Web中默认使用的相同HttpMessageConverters。 Spring Cloud集成了Ribbon和Eureka以及Spring Cloud LoadBalancer,以在使用Feign时提供负载平衡的http客户端。
1.2 特点
在一般的场景中,如果要发送 http 请求,需要根据服务提供方的 ip、端口、url 进行调用,openfeign 提供了一种基于接口的调用方式。
- 原始的调用方法: client.request(“http://ip:port/service”);
- openfeign 调用方法:service.request(args); openfeign 根据服务名进行调用,调用方配置服务提供方的服务名 spring.application.name ;
使用 openfeign 调用远程服务就像 java 代码中接口调用方法一样,不用再编写复杂的 http 请求逻辑;如果集成了 eureka 等注册中心,甚至不用配置服务提供方的 url,只需配置 eureka 即可。
2.演示环境
- JDK 1.8.0_201
- Spring Boot 2.2.0.RELEASE、Spring Cloud Hoxton.RELEASE
- 构建工具(apache maven 3.6.3)
- 开发工具(IntelliJ IDEA )
3.演示代码
Feign+Eureka+Hystrix 的混合运用
总体结构说明:
- ofc-feign-eureka-server: eureka 服务端,提供服务注册功能;
- ofc-feign-user-api: 公共 api,定义模型和接口,fallback;
- ofc-feign-user-client: 服务调用方,使用 feign 调用接口,注册到 eureka server;
- ofc-feign-user-server: 服务提供方,实现 api 中定义的接口,注册到 eureka server。
3.1 ofc-feign-eureka-server
3.1.1 代码说明
eureka 服务端,提供服务注册功能。
3.1.2 maven 依赖
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
3.1.3 配置文件
application.properties
spring.application.name=ofc-feign-eureka-server
# 应用服务web访问端口
server.port=11040
# 服务注册中心主机名
eureka.instance.hostname=localhost
# 是否注册自己
eureka.client.register-with-eureka=false
# 是否检索服务
eureka.client.fetch-registry=false
# eureka server 地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
3.1.4 java代码
OfcFeignEurekaApplication.java
// 开启 eureka server
@EnableEurekaServer
@SpringBootApplication
public class OfcFeignEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(OfcFeignEurekaApplication.class, args);
}
}
3.2 ofc-feign-user-api
3.2.1 代码说明
公共 api,定义了实体模型,公共接口以及 fallback 类。
3.2.2 maven 依赖
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
3.2.3 配置文件
application.properties
spring.application.name=ofc-feign-user-api
# 应用服务web访问端口
server.port=8080
3.2.4 java代码
UserModel.java
public class UserModel {
private Long id;
private String name;
private Integer age;
private String birthday;
private String address;
private String phone;
public UserModel() {
}
public UserModel(Long id, String name, Integer age, String birthday, String address, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.birthday = birthday;
this.address = address;
this.phone = phone;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "UserModel{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", birthday='" + birthday + '\''
+ ", address='" + address + '\'' + ", phone='" + phone + '\'' + '}';
}
}
UserService.java
// value 中定义服务提供者名称,fallback-降级
@FeignClient(value = "ofc-feign-user-server", fallback = UserServiceFallback.class)
public interface UserService {
@GetMapping(value = "/user/list")
List<UserModel> list();
@PostMapping(value = "/user/save")
UserModel save(@RequestBody UserModel userModel);
}
UserServiceFallback.java
public class UserServiceFallback implements UserService {
@Override
public List<UserModel> list() {
return Collections.emptyList();
}
@Override
public UserModel save(UserModel userModel)