Spring Boot 2.1.x Spring Cloud Greenwich.SRx

一、Feign Contract 作用

1.1、基于 spring boot 如何编写 Feign 调用

Spring Boot + Feign 是远程 RPC 的一种实现方案,通常在代码中,定义一个远程API会采用接口的方式,使用 Spring MVC的方式定义一个远程调用,如:使用对应的 annotation ,@RequestParam@RequestBody等。
学习成本低,编写风格也和编写 Spring Mvc 接口一致,很简单就定义了相关的远程 RPC 调用接口。

参考代码如下:
image.png

1.2、Feign contract 作用

《Feign如何进行服务间请求调用#Feign Clietn 调用流程》中讨论 Feign 进行服务间调用的本质就是拼接 RequestTemplate 对象,发起 HTTP 请求。

拼接 HTTP 请求通常会涉及到几个问题点:

  • 1、常见的 POST 还是 GET ,或者 DELETE 等请求方法
  • 2、参数存放到表单,还是使用 JSON 字符串
  • 3、请求 URL 定义

再来对照一下平时写代码时关于 Feign 接口的定义:
image.png

通过代码,能够想象得到,通过解析接口(标记了 @FeignClient 标识的接口)方法上的相关注解定义就能够得到拼接 HTTP 请求所需的参数

  • 如:@RequestMapping 定义的 POST 方法
  • 如:@RequestMapping定义的资源访问路径
  • 如:方法参数上 @RequestBody定义了传输方式使用的 JSON 字符串格式

在 Feign 代码中完成该项工作的是 feign.Contract

二、关于 Contract 的实现

Spring Boot 集成 Feign + Hystrix 后相关实现

image.png

2.1、Contract 接口定义

image.png
根据 Contract源码及注释能够得到

  • Contract 定义了Contract#parseAndValidatateMetadata方法用来解析 Feign 接口从而得到 Http 请求所需相关参数
  • 通过 Contract 能够定义不同Feign 接口解析方案

    2.2、BaseContract 模板抽象类

    BaseContractContract模板抽象实现,BaseContract定义了关于 Feign接口的基础模板流程

  • 接口格式校验

  • 解析 Feign 接口标注的 Annotation ,然后构建 MethodMetadata对象存储相关数据。

其中具体的解析方法作为模板方法,需要对应的子类自行实现,对应的解析操作有

  • 类注解解析(BaseContract#processAnnotationOnClass)
  • 方法注解解析(BaseContract#processAnnotationOnMethod)
  • 方法参数注解解析(BaseContract#processAnnotationsOnParameter)

2.2.1、Default 继承模板抽象类 BaseContract

参考文档:open feign interface annotations

feign.Default继承了模板抽象类 BaseContract,同时实现了三个解析方法

  • 类注解解析(Default #processAnnotationOnClass)
  • 方法注解解析(Default #processAnnotationOnMethod)
  • 方法参数注解解析(Default #processAnnotationsOnParameter)

feign.Default是 open feign 官方模式实现,主要解析的注解有
image.png
对应相关源码如下

类注解解析

image.png

方法注解解析

image.png

方法参数注解解析

image.png

2.2.1、SpringMvcContract 继承模板抽象类 BaseContract

SpringMvcContract是 Spring Cloud 集成 Open Feign 后,针对 Spring MVC 代码编写风格而特定的解析类,通过该类,用户可以直接使用 Spring MVC 的编码风格编写 Feign RPC 调用代码。

同样的 SpringMvcContract继承自了模板抽象类 BaseContract,主要的实现同样是三个解析方法的实现

类注解解析

image.png

方法注解解析

image.png

方法参数解析

image.png
针对不同类型的方法参数提供不同解析器

  • PathVariableParameterProcessor针对 URL 入参的解析
  • QueryMapParameterProcessor针对 @SpringQueryMap入参注解解析
  • RequestHeaderParameterProcessor针对 @RequestHeader入参注解解析
  • RequestParamParameterProcessor针对 @RequestParam入参注解解析

2.3、HystrixDelegatingContract

feign 集成 Hystrix 后,请求会被 HystrixCommand代理,对应的返回值也不再是编码时方法的返回值,,HystrixDelegatingContract类新增了对返回类型的解析处理。

相关源码如下
image.png

从代码能够知道
HystrixDelegatingContract采用装饰模式,对已有的 Contract增强集成 Hystrix 而导致返回值无法正确解析的解析处理。

在 Spring Boot 集成项目中,被装饰的对象实例通常为 SpringMvcContract