目录
优雅实现远程调用-OpenFeign
RestTemplate存在问题
观察我们远程调⽤的代码
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.
在SpringCloud中, 默认是使⽤HTTP来进⾏微服务的通信, 最常⽤的实现形式有两种:
- RestTemplate
- OpenFeign
RPC(Remote Procedure Call)远程过程调⽤,是⼀种通过⽹络从远程计算机上请求服务,⽽不需要了解底层⽹络通信细节。RPC可以使⽤多种⽹络协议进⾏通信, 如HTTP、TCP、UDP等, 并且在TCP/IP⽹络四层模型中跨越了传输层和应⽤层。简⾔之RPC就是像调⽤本地⽅法⼀样调⽤远程⽅法。
常⻅的RPC框架有:
- Dubbo: Apache Dubbo 中⽂
- Thrift : Apache Thrift - Home
- gRPC: gRPC
OpenFeign介绍
OpenFeign 是⼀个声明式的 Web Service 客⼾端. 它让微服务之间的调⽤变得更简单, 类似controller调⽤service, 只需要创建⼀个接⼝,然后添加注解即可使⽤OpenFeign.
OpenFeign 的前⾝
Feign 是 Netflix 公司开源的⼀个组件.
-
2013年6⽉, Netflix发布 Feign的第⼀个版本 1.0.0
-
2016年7⽉, Netflix发布Feign的最后⼀个版本 8.18.0
2016年,Netflix 将 Feign 捐献给社区
-
2016年7⽉ OpenFeign 的⾸个版本 9.0.0 发布,之后⼀直持续发布到现在.
可以简单理解为 Netflix Feign 是OpenFeign的祖先, 或者说OpenFeign 是Netflix Feign的升级版.
OpenFeign 是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
OpenFeign 官⽅⽂档: GitHub - OpenFeign/feign: Feign makes writing java http clients easier
Spring Cloud Feign⽂档: Spring Cloud OpenFeign
快速上手
因为 Feign 的学习是基于 Nacos 的代码进行开发的,因此复制 spring-cloud-nacos 项目为 spring-cloud-feign,记得修改对应的 pom.xml 文件
引入依赖
在 order-service 中
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
添加注解
在order-service的启动类添加注解 @EnableFeignClients , 开启OpenFeign的功能.
@EnableFeignClients
@SpringBootApplication
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
编写OpenFeign的客户端
基于SpringMVC的注解来声明远程调⽤的信息
在 api 包下
@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 属性指定⼀个具体的url.
- path: 定义当前FeignClient的统⼀前缀.
远程调用
修改远程调⽤的⽅法
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@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接⼝, 并通过注解的⽅式来声明请求参数,请求⽅式等信息, 使远程调⽤更加⽅便和间接.
OpenFeign参数传递
通过观察, 我们也可以发现, Feign的客⼾端和服务提供者的接⼝声明⾮常相似
上⾯例⼦中, 演⽰了Feign 从URL中获取参数, 接下来演⽰下Feign参数传递的其他⽅式
只做代码演⽰, 不做功能
传递单个参数
服务提供⽅ product-service
@RequestMapping("/product")
@RestController
public class ProductController {
@RequestMapping("/p1")
public String p1(Integer id){
return "p1接收到参数:" + id;
}
}
Feign客⼾端
@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {
@RequestMapping("/p1")
String p1(@RequestParam("id"

最低0.47元/天 解锁文章
1276

被折叠的 条评论
为什么被折叠?



