OpenFeignSpring Cloud 里用来做服务调用的工具

OpenFeign 可以让你像调用本地 Java 方法一样,去调用另一个微服务的接口。

在一个简单的下单储存的项目里,就是:

order 服务调用 stock 服务

以前可能用 RestTemplate,现在更常用 OpenFeign


1. 没有 OpenFeign 时怎么调用?

比如 order 服务要调用 stock 服务扣库存。

RestTemplate 可能这样写:

String result = restTemplate.getForObject(
    "http://stock-service/stock/reduct",
    String.class
);

这段代码的意思是:

order 服务主动发送 HTTP 请求,调用 stock 服务的 /stock/reduct 接口

但是这种写法有点像 Python 里的:

requests.get("http://stock-service/stock/reduct")

能用,但写多了会乱。


2. OpenFeign 是怎么做的?

OpenFeign 的思想是:

只需要写一个 Java 接口,告诉它要调用哪个服务、哪个接口,剩下的 HTTP 请求由 OpenFeign 自动完成

比如:

@FeignClient("stock-service")
public interface StockFeignService {

    @GetMapping("/stock/reduct")
    String reduct();
}

这段代码看起来只是一个接口,但它的意思是:

我要调用名叫 stock-service 的服务
调用它的 /stock/reduct 接口
返回 String 结果

然后在 order 服务里直接调用:

stockFeignService.reduct();

这就像调用本地方法一样。


3. OpenFeign 在 order + stock 项目里的位置

你的项目大概是:

xs-springcloudalibaba
├── order
└── stock

业务流程是:

浏览器 / Postman
    ↓
order 服务:/order/add
    ↓
OpenFeign 调用
    ↓
stock 服务:/stock/reduct

也就是说:

OpenFeign 负责 order 服务调用 stock 服务

4. RestTemplate 和 OpenFeign 的区别

方式 写法 特点
RestTemplate 手动拼 URL 比较原始
OpenFeign 写接口调用 更优雅,更适合微服务

RestTemplate 写法

restTemplate.getForObject(
    "http://stock-service/stock/reduct",
    String.class
);

OpenFeign 写法

stockFeignService.reduct();

明显后者更像正常 Java 方法调用。


5. OpenFeign 怎么用?


第一步:在 order 服务的 pom.xml 加依赖

因为是 order 调用别人,所以依赖加在 order 服务里。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

如果你还用 Nacos 服务发现,也要有 Nacos 依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

第二步:在启动类上开启 Feign

OrderApplication.java

@SpringBootApplication
@EnableFeignClients
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

重点是这个注解:

@EnableFeignClients

意思是:

开启 OpenFeign 功能。


第三步:写 Feign 接口

在 IDEA 里的目录结构大概是:

order
└── src
    └── main
        └── java
            └── com.tulingxueyuan.order
                ├── controller
                │   └── OrderController.java
                ├── feign
                │   └── StockFeignService.java
                └── OrderApplication.java

order 服务下面建一个包:

com.tulingxueyuan.order.feign

然后写:

package com.tulingxueyuan.order.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("stock-service")
public interface StockFeignService {

    @GetMapping("/stock/reduct")
    String reduct();
}

解释一下:

@FeignClient("stock-service")

表示:

我要调用 Nacos 里名字叫 stock-service 的服务
@GetMapping("/stock/reduct")

表示:

我要调用 stock-service 服务里的 /stock/reduct 接口

6. Controller 里怎么用?

OrderController.java

package com.tulingxueyuan.order.controller;

import com.tulingxueyuan.order.feign.StockFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private StockFeignService stockFeignService;

    @GetMapping("/add")
    public String add() {

        System.out.println("创建订单成功");

        String result = stockFeignService.reduct();

        return "下单成功," + result;
    }
}

当你访问:

http://localhost:8081/order/add

执行过程是:

进入 OrderController 的 add()
    ↓
打印:创建订单成功
    ↓
调用 stockFeignService.reduct()
    ↓
OpenFeign 自动请求 stock 服务的 /stock/reduct
    ↓
stock 服务返回结果
    ↓
order 服务把结果返回给浏览器

7. stock 服务要有什么接口?

StockController.java

package com.tulingxueyuan.stock.controller;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/stock")
public class StockController {

    @GetMapping("/reduct")
    public String reduct() {
        System.out.println("扣减库存成功");
        return "库存扣减成功";
    }
}

8. Nacos 和 OpenFeign 的关系

OpenFeign 本身负责:

发起服务调用

Nacos 负责:

告诉 OpenFeign:stock-service 到底在哪台机器、哪个端口

比如 stock-service 注册到 Nacos:

stock-service -> 127.0.0.1:8082

那么 OpenFeign 调用:

@FeignClient("stock-service")

它会去 Nacos 找 stock-service 的真实地址。

所以它们的关系是:

Nacos:负责找服务
OpenFeign:负责调用服务

9. 可以这样记

在 Spring Cloud Alibaba 里:

Nacos:服务注册与发现
OpenFeign:服务之间互相调用
Seata:保证多个服务的数据一致
Sentinel:限流、熔断、降级

针对你的项目:

order 调用 stock:用 OpenFeign
order 找到 stock:靠 Nacos
order 和 stock 事务一致:靠 Seata

10. 总结

OpenFeign 就是微服务之间的 HTTP 调用工具。

它把这种写法:

restTemplate.getForObject("http://stock-service/stock/reduct", String.class);

变成这种写法:

stockFeignService.reduct();

所以可以先记住:

OpenFeign 的作用是:让一个服务调用另一个服务时,写起来像调用本地方法一样。

更多推荐