前言
在讲前面几篇文章的时候,消费者服务与提供者服务之间是利用RestTemplate
进行通信的。这种方式是属于面向服务编程,那么在实际开发中,对服务依赖的客户端可能会有很多,每个客户端都需要对这些依赖的服务调用进行封装,大大增加的工作量。因此,SpringCloud就提供了一种解决方案,面向接口编程的声明式服务调用——Feign
,只需简单的声明一下微服务接口,即可进行服务之间的通信,从而大大减轻的工作量。
什么是Feign?
Feign
是一个声明式WebService
客户端。使用Feign
能让编写Web Service
客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS
标准的注解。Feign
也支持可拔插式的编码器和解码器。Spring Cloud
对Feign
进行了封装,使其支持了Spring MVC
标准注解和HttpMessageConverters
。Feign
可以与Eureka
和Ribbon
组合使用以支持负载均衡。
官方介绍:http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign
GitHub:https://github.com/OpenFeign/feign
前面在使用RestTemplate时,利用RestTemplate
对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处, 往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。 所以,Feign
在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign
的实现下, 我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可) ,即可完成对服务提供方的接口绑定,优雅而简单的实现了服务调用 ,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。
集成Feign
创建一个名称为spring-cloud-api
的module
:
修改pom
文件,增加feign
依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-examples</artifactId>
<groupId>com.chaytech</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-api</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.chaytech</groupId>
<artifactId>spring-cloud-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
</project>
创建一个名称为UserApi
的接口,并添加FeignClient
注解:
@FeignClient(value = "USER-PROVIDER")
public interface UserApi {
@PostMapping("/user/createUser")
public boolean createUser(@RequestBody UserEntity user);
@GetMapping("/user/getUser/{id}")
public UserEntity getUser(@PathVariable("id") Integer id);
@GetMapping("/user/listUser")
public List<UserEntity> listUser();
}
将此工程maven install
,如果打包失败,找到父工程,maven install
创建feign
客户端module
(spring-cloud-consumer-user-feign
):
将spring-cloud-consumer-user
的代码和配置文件copy一份到此工程下。
修改pom
文件,增加feign
依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-examples</artifactId>
<groupId>com.chaytech</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-consumer-user-feign</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.chaytech</groupId>
<artifactId>spring-cloud-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.chaytech</groupId>
<artifactId>spring-cloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- ribbon相关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
修改UserController
,将原有的RestTemplate
调用方式修改为feign
调用:
@RestController
public class UserController {
@Autowired
private UserApi userApi;
@PostMapping("/consumer/user/add")
public boolean add(UserEntity user) {
return userApi.createUser(user);
}
@GetMapping("/consumer/user/getUser/{id}")
public UserEntity get(@PathVariable("id") Integer id) {
return userApi.getUser(id);
}
@GetMapping("/consumer/user/listUser")
public List<UserEntity> list() {
return userApi.listUser();
}
}
修改启动类,增加@EnableFeignClients
注解:
此处注意,如果你的feign
接口的包路径与feign
客户端路径不一致,则需要指定basePackages
,否则将会扫描不到feign
接口,导致注入失败。
@SpringBootApplication
// 本服务启动后会自动注册进eureka服务中
@EnableEurekaClient
@EnableFeignClients(basePackages ={"com.chaytech.api"} )
public class UserConsumerFeign80_Application {
public static void main(String[] args) {
SpringApplication.run(UserConsumerFeign80_Application.class,args);
}
}
测试
分别启动eureka
集群、部门微服务集群、feign
客户端服务
还是请求同一个地址:127.0.01:8080/consumer/user/listUser
接口正常返回数据,至此,集成feign
进行声明式服务调用成功!