声明式调用Feign是如何匹配接口的?

在Feign的Service添加了FeignCLient(name = "XXX-SERVICE"),定义好了接口之后,Feign是通过什么方式找到服务提供者的接口的?是通过RequestMapping中的value吗?

阅读 3.7k
2 个回答

如果题主的『如何』指的是如何使用 Feign 通过声明式的注解,提供一个供其它服务调用的 Client。

这里先举个例子说明:
在一个 Spring Cloud 项目中,你通过如下代码声明一个服务:

1. 配置文件 bootstrap.yml:

spring:
  application:
    name: mock-service

2. Endpoint 定义文件 MockController:

@RestController
public class MockController {

    @GetMapping(value = "/mocks")
    public ResponseObj getMethod() {

        ResponseObj responseObj = new ResponseObj();
        responseObj.setRetCode(ResponseObj.CODE_SUCCESS);
        responseObj.setRetMsg("获取对象");
        return responseObj;

    }

    @PutMapping(value = "/mocks")
    public ResponseObj modifyMethod(@RequestBody MockReq mockReq) {

        ResponseObj responseObj = new ResponseObj();
        responseObj.setRetCode(ResponseObj.CODE_SUCCESS);
        responseObj.setRetMsg("修改对象: "+ mockReq.getMessage());
        return responseObj;

    }

    @PostMapping(value = "/mocks")
    public ResponseObj addMethod(@RequestBody MockReq mockReq) {

        ResponseObj responseObj = new ResponseObj();
        responseObj.setRetCode(ResponseObj.CODE_SUCCESS);
        responseObj.setRetMsg("增加对象: " + mockReq.getMessage());
        return responseObj;

    }

    @DeleteMapping(value = "/mocks")
    public ResponseObj deleteMethod(@RequestBody MockReq mockReq) {

        ResponseObj responseObj = new ResponseObj();
        responseObj.setRetCode(ResponseObj.CODE_SUCCESS);
        responseObj.setRetMsg("删除对象: "+ mockReq.getMessage());
        return responseObj;

    }
}

3. Feign Client 定义文件 MockClient.java:

@FeignClient(value = "mock-service")
public interface MockClient {

    @GetMapping(value = "/mocks")
    ResponseObj getMethod();

    @PostMapping(value = "/mocks")
    ResponseObj postMethod(@RequestBody MockReq mockReq);

    @PutMapping(value = "/mocks")
    ResponseObj putMethod(@RequestBody MockReq mockReq);

    @DeleteMapping(value = "/mocks")
    ResponseObj deleteMethod(@RequestBody MockReq mockReq);

}

由 1、2、3 得出结论,Feign 提供的是对 特定服务 > 特定接口 的声明式定义。换言之,也就是先找到服务,然后寻找服务里的接口。

如果题主中的『如何』指的是:上述调用方如何找到 mock-service 服务。在 Spring Cloud Netflix 中,Eureka Server (注册中心)负责服务注册与发现,同一个注册中心中的服务可以通过 Feign 进行声明式调用。其原理是通过注解,把请求模板化。当请求参数传进来的时候,会把参数填充到模板中去,然后调用类似于下面伪代码:

ResponseObj responseObj = HttpClient.getObj(mockReq, 'http://api.example.com/mocks', ResponseObj.class);

可以看成是一个远程方法调用,其中 HttpEncoder 和 HttpDecoder 等其它细节,不详细展开。

我个人的理解是FeignClient中的接口名称的定义与服务提供者中的controller中的接口名称一致,就实现了Feign接口与被调用服务的接口的捆绑。

不知道这样的理解对不对?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题