文章目录
- [RestTemplate 存在问题](#RestTemplate 存在问题)
- [OpenFeign 介绍](#OpenFeign 介绍)
-
-
- [OpenFeign 前身](#OpenFeign 前身)
- [Spring Cloud Feign](#Spring Cloud Feign)
-
- 快速上手
RestTemplate 存在问题
观察我们远程调用的代码
java
public OrderInfo selectOrderById(Integer orderId) {
OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
String url = "http://product-service/product/" + orderInfo.getProductId();
ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
orderInfo.setProductInfo(productInfo);
return orderInfo;
}
虽说 RestTemplate 对 HTTP 封装之后,已经比直接使用 HTTPClient 要简单方便很多,但是还是存在一些问题
- 需要拼接
URL,灵活性高,但是封装臃肿,URL复杂时,容易出错 - 代码可读性差,风格不统一
微服务之间的通信方式,通常有两种:RPC 和 HTTP
在 Spring Cloud 中,默认是使用 HTTP 来进行微服务的通信,最常用的实现形式有两种:
RestTemplateOpenFeign
RPC(Remote Procedure Call)远程过程调用
- 是一种通过网络从远程计算机上请求服务,而不需要了解底层网络通信机制
RPC可以使用多种网络协议进行通信,如HTTP、TCP、UDP等,并且在TCP/IP网络四层模型中跨越了传输层和应用层- 简而言之
RPC就是像调用本地方法一样调用远程方法- 常见的
RPC框架有:
DubboThriftgRPC
OpenFeign 介绍
OpenFeign 是一个声明式的 Web Service 客户端。它让微服务之间的调用变得更简单,类似 controller 调用 service,只需要创建一个接口,然后添加注解即可使用 OpenFeign
OpenFeign 前身
Feign 是 NetFlix 公司开源的一个组件
可以简单理解为 NetFlix Feign 是 OpenFeign 的祖先,或者说 OpenFeign 是 NetFlix Feign 的升级版,是一个更强大更灵活的实现
现在网络上看到的文章,或者公司用的
Feign,大多都是OpenFeign,我们后面讲说的Feign,指的是OpenFeign
Spring Cloud Feign
Spring Cloud Feign 是 Spring 对 Feign 的封装,将 Feign 项目继承到 Spring Cloud 生态系统中。
受 Feign 更名影响,Spring Cloud Feign 也有两个 starter
spring-cloud-starter-feignspring-cloud-starter-openfeign
由于 Feign 的停更维护,对应的,我们使用的依赖是 `spring-cloud-starter-openfeign```
快速上手
引入依赖
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
添加注解
在 order-service 的启动类添加注解 @EnableFeignClients
java
@EnableFeignClients
@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
编写 OpenFeign 的客户端
基于 SpringMVC 的注解来声明远程调用的信息
java
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {
@RequestMapping("/{productId}")
ProductInfo getProductById(@PathVariable("productId") Integer productId);
}
@FeignClient注解作用在接口上,参数说明name/value:指定FeignClient的名称,也就是微服务的名称,用于服务发现,Feign底层会使用Spring Cloud LoadBalance进行负载均衡。也可以使用url属性指定一个具体的urlpath:定义当前FeignClient的统一前缀
远程调用
修改远程调用的方法
java
public class OrderService {
//...
@Autowired
private ProductApi productApi;
//...
// Feign 实现远程调用
public OrderInfo selectOrderById(Integer orderId) {
OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
ProductInfo productInfo = productApi.getProductById(orderInfo.getProductId());
orderInfo.setProductInfo(productInfo);
return orderInfo;
}
}
- 代码对比:

测试
启动服务,访问接口,测试远程调用:
- http://127.0.0.1:8080/order/1

可以看出来,使用Feign也可以实现远程调用
Feign 简化了与 HTTP 服务交互的过程,把 REST 客户端的定义转换为 Java 接口,并通过注解的方式来声明请求参数,请求方式等信息,使远程调用更加方便和间接