[SpringCloud] OpenFeign 微服务通信快速上手

引入 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