引入 OpenFeign
微服务间进行通信主要通过 HTTP 和 RPC 两种方式进行
SpringCloud 中 HTTP 的实现形式 除了RestTemplate 还有OpenFeign
OpenFeign 是一个声明式的 Web Service 客户端。它让微服务之间的调用变得更简单,类似 controller 调用 service,只需要创建一个接口,然后添加注解即可使用 OpenFeign
引入Spring Cloud Feign
Spring Cloud Feign 是 Spring 对 Feign 的封装,将 Feign 项目集成到 Spring Cloud 生态系统中。受 Feign 更名影响,Spring Cloud Feign 也有两个 starter:
- spring-cloud-starter-feign
- spring-cloud-starter-openfeign
OpenFeign 官方文档 : GitHub - OpenFeign/feign: Feign makes writing java http clients easier · GitHub
Spring Cloud Feign 文档 : Spring Cloud OpenFeign
快速上手
① 引入依赖
在 order-service (对需要远程通信的项目) 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
② 通过注解 , 开启 Feign 功能
在 order-service 的启动类中加入注解
@EnableFeignClients

③ 编写客户端 并 修改远程调用

java
import com.boop.order_service.model.ProductInfo;
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")
/**
* value 是指定服务名称,用于服务发现
* path url前缀
*/
public interface ProductAPI {
@RequestMapping("/{productId}") //关联url
ProductInfo getProductInfo(@PathVariable("productId") Integer productInfo); //关联参数
}
java
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private ProductAPI productAPI;
public OrderInfo selectOrderById(Integer orderId){
OrderInfo info = orderMapper.selectOrderById(orderId);
ProductInfo productInfo = productAPI.getProductInfo(info.getProductId());
info.setProductInfo(productInfo);
return info;
}
}
④ 测试http://127.0.0.1:9096/order/1

OpenFeign 参数传递

productService(服务提供方) : 被调用的服务 , 提供具体的业务接口(controller)
FeignClient(Feign 客户端) : 消费方的接口 , 用于定义如何调用提供方 ; 可以通过注解将 HTTP 请求映射为 Java 方法使用
OrderService(服务消费方) : 发起调用服务 , 注入 Feign 客户端 , 像本地方法一样调用远程服务
传递一个或多个参数

ProductAPI
java
@FeignClient(value = "product-service", path = "/product")
/**
* value 是指定服务名称,用于服务发现
* path url前缀
*/
public interface ProductAPI {
@RequestMapping("/{productId}") //关联url
ProductInfo getProductInfo(@PathVariable("productId") Integer productInfo); //关联参数
@RequestMapping("/p1")
String p1(@RequestParam("id") Integer id);
}
ProductController
java
@RequestMapping("/product")
@RestController
public class ProductController {
@Resource
private ProductService productService;
@RequestMapping("/{productId}")
public ProductInfo getProductById(@PathVariable("productId") Integer productId){
return productService.selectProductById(productId);
}
/***
* OpenFeign参数传递
*/
//传递单个参数
@RequestMapping("/p1")
public String p1(@RequestParam("id")Integer id){
return "product-service 接收到的参数" +id;
}
}
TestFeignController
java
@RequestMapping("/feign")
@RestController
public class TestFeignController {
@Autowired
private ProductAPI productAPI;
@RequestMapping("o1")
public String p1(Integer id){
return "接收到参数 ,id:"+id;
}
}
测试 :
http://127.0.0.1:9096/feign/o1?id=2

过程讲解( 重点 ):
调用关系 : 用户访问 http://127.0.0.1:9096/feign/o1?id=2=> TestFeignController 接收 并调用 ProductAPI.p1(2) =>OpenFiegn 构造 http 请求( http://127.0.0.1:9095/product/p1?id=2) , 发给 Nacos 上的 product-service 实例 => ProductController.p1(2) =>返回字符串

传递对象
ProductAPI
java
@RequestMapping("/p2")
public String p2(@SpringQueryMap ProductInfo productInfo);
ProductController
java
//传递对象
@RequestMapping("/p2")
public String p2(@SpringQueryMap ProductInfo productInfo){
return "product-service 接收到的参数" +productInfo.toString();
}
TestFeignController
java
@RequestMapping("o2")
public String o2(){
ProductInfo productInfo = new ProductInfo();
productInfo.setProductName("zhangsan");
productInfo.setId(54);
return productAPI.p2(productInfo);
}
测试 :
http://127.0.0.1:9096/feign/o2

传递 JSON
ProductAPI
java
@RequestMapping("/p3")
public String p3(@RequestBody ProductInfo productInfo);
ProductController
java
//传递JSON
@RequestMapping("/p3")
public String p3(@RequestBody ProductInfo productInfo) {
return "product-service 接收到的参数" + productInfo;
}
TestFeignController
java
@RequestMapping("o3")
public String o3(){
ProductInfo productInfo2 = new ProductInfo();
productInfo2.setProductName("zhangsan");
productInfo2.setId(54);
return productAPI.p3(productInfo2);
}
测试 : http://127.0.0.1:9096/feign/o3
