Feign是一种声明式、模板化的HTTP客户端(仅在 consumer 中使用)。
声明式调用就像调用本地方法一样调用远程方法;无感知远程 http 请求。
我们模拟一个分布式电商系统中消费者通过注册中心(eureka)获取提供者提供的获取商品信息的服务的场景。
组件说明
服务 | 说明 |
---|---|
eureka集群 | 注册中心,提供服务的注册和发现 |
service服务 | 声明service接口,定义方法,provider和consumer都需要依赖此服务而且接口中的方法需要使用到SpringMVC的主键 |
provider服务 | 提供商品信息查询服务,需要依赖service服务 |
consumer服务 | 服务消费者,需要依赖service服务,同时通过feign调用provider的服务获取商品信息 |
创建一个普通的SpringBoot项目,因为要在接口中使用SpringMVC的主键,所以我们就直接创建了一个SpringBoot项目
因为需要使用@RequestMapping主键,所以添加如下依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
在接口声明服务的功能,同时在本服务中声明pojo类,就不再单独创建pojo项目了。
/**
* @program: springcloud-feign-prodcut-service
* @description: 商品信息的pojo类
* @author: 波波烤鸭
* @create: 2019-06-07 09:22
*/
public class Product {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Product() {
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Product(Integer id, String name) {
this.id = id;
this.name = name;
}
}
服务接口
/**
* 公共服务的接口
*/
@RequestMapping("/product")
public interface ProductService {
/**
* 查询所有商品的方法
* @return
*/
@GetMapping("/findAll")
public List<Product> findAll();
}
最后将服务打包即可
provider提供商品信息的查询服务,同时需要在eureka中注册,具体实现如下:
注意需要添加service服务的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- 注意:需要添加 service服务的依赖 -->
<dependency>
<groupId>com.dpb</groupId>
<artifactId>springcloud-feign-prodcut-service</artifactId>
<version>1.0.1-RELEASE</version>
</dependency>
</dependencies>
添加服务名称,端口及eureka注册中心的信息
spring.application.name=shop-product-provider
server.port=9091
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://dpb:123456@eureka1:8761/eureka/,http://dpb:123456@eureka2:8761/eureka/
控制器中实现service中的接口
/**
* @program: springcloud-feign-product-provider
* @description: 服务提供者的控制器
* @author: 波波烤鸭
* @create: 2019-06-07 09:44
*/
@RestController
public class ProductController implements ProductService{
/**
* 此处不用再添加@RequestMapping注解,重写的方法在接口中定义的有
* @return
*/
@Override
public List<Product> findAll() {
List<Product> list = new ArrayList<>();
list.add(new Product(1, "电视"));
list.add(new Product(2, "电脑"));
list.add(new Product(3, "冰箱"));
list.add(new Product(4, "洗衣机"));
return list;
}
}
添加eureka客户端的注解,然后启动服务
@EnableEurekaClient
@SpringBootApplication
public class SpringcloudFeignProductProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudFeignProductProviderApplication.class, args);
}
}
需要添加service服务的依赖以及feign的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 添加 Feign 坐标 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<!-- 注意:需要添加 service服务的依赖 -->
<dependency>
<groupId>com.dpb</groupId>
<artifactId>springcloud-feign-prodcut-service</artifactId>
<version>1.0.1-RELEASE</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
spring.application.name=shop-product-consumer
server.port=9090
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://dpb:123456@eureka1:8761/eureka/,http://dpb:123456@eureka2:8761/eureka/
本接口继承自service中的接口,添加@FeignClient接口,指定provider的服务名称。
@FeignClient(name="shop-product-provider")
public interface ProductConsumerService extends ProductService {
}
/**
* @program: springcloud-feign-prodcut-consumer
* @description: 消费者提供服务
* @author: 波波烤鸭
* @create: 2019-06-07 10:47
*/
@RestController
public class ProductController {
@Autowired
ProductConsumerService consumerService;
/**
* Consumer 中的查询所有商品的方法
* @return
*/
@RequestMapping(value="/list",method= RequestMethod.GET)
public List<Product> getAll(){
return this.consumerService.findAll();
}
}
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class SpringcloudFeignProdcutConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudFeignProdcutConsumerApplication.class, args);
}
}
分别启动provider和consumer,然后访问consumer的服务,如下