使用原生的 Feign 进行 HTTP 调用

本贴最后更新于 1579 天前,其中的信息可能已经东海扬尘

前言

在最开始学习 Spring Cloud 的时候,了解其中有个组件叫做 Feign : 可以通过既定规则在本地消费端存留一份服务提供者的接口,这样消费者便可以直接通过这个接口来进行服务消费。

Spring Cloud 是一个开源方案的整合体,其中的 Feign 组件整合的就是已有的一个开源组件 Feign

Feign 的中文含义是: 假装!

背景

最近有个项目需要调用第三方提供的 HTTP 接口,这个项目不是基于 Spring Cloud 的,所以 Spirng Cloud 已整合的 Feign 无法使用。

最开始考虑使用 Spring 自带的 HttpRestemplate 但是随着项目编码,发现这种方式使用其他不够方便,每次调用都要写一大堆代码:请求、处理响应、重试这些都需要自己处理,颇多不便。

正好想起了 Feign 这个开源组件,所以经过一番学习,重新引入了原生的 Feign 进行 HTTP 的调用,这里将学的东西做个简单记录。

服务提供者

先将服务提供者的 demo 代码附上

@RequestMapping("/stu") @RestController public class StuProvider { @GetMapping public StudentVo getBook(@RequestParam("id") String id) { System.out.println("id is " + id); return JMockData.mock(StudentVo.class); } @PostMapping public StudentVo postBook(@RequestBody StudentVo bookVo) { System.out.println(bookVo.toString()); return bookVo; } @PostMapping("/map") public Map<String, StudentVo> postBook(@RequestBody List<StudentVo> bookVo) { System.out.println(bookVo.toString()); return JMockData.mock(new TypeReference<Map<String, StudentVo>>() { }); } @PostMapping("/param") public StudentVo postParam(@RequestParam("id") String id) { System.out.println("收到的id为:" + id); return JMockData.mock(StudentVo.class); } }

Feign 接口

public interface StuApi { @Headers("Content-Type: application/json") @RequestLine("GET /stu?id={id}") StudentVo getBook(@Param("id") String id); @Headers({"Content-Type: application/json", "Accept: application/json"}) @RequestLine("POST /stu") StudentVo postBook1(StudentVo bookVo); @Headers({"Content-Type: application/json", "Accept: application/json"}) @RequestLine("POST /stu/map") Map<String, StudentVo> postBook2(List<StudentVo> bookVo); @Headers({"Content-Type: application/json", "Accept: application/json"}) @RequestLine("POST /stu/param?id={id}") StudentVo postParam(@Param("id") String id); }

@Headers

@Headers 这个注解需要指明请求的类型和响应类型。

  1. 如果只有响应的是 json,那么如第一个 api 所示
@Headers("Content-Type: application/json")
  1. 如果请求和相应都是 json 格式,那么如后面 3 个所示:
@Headers({"Content-Type: application/json", "Accept: application/json"})

实际测试后发现,只要是 @RestController 修饰的提供者,不管请求和响应类型,直接采用第二种都可以。

但是如果请求和响应都是 json,那么如果不些 @Headers 这个注解,肯定报错。比如后续的 2 3 4 这 3 个 API.

@RequestLine

通过 @RequestLine 来标明当前接口的类型。

比如如下 API 标明的就是 Get 请求

@RequestLine("GET /stu?id={id}")

Post 的类似

@RequestLine("POST /stu")

使用方法

构建了上述接口后,那么如何使用了,Feign 提供了基于 Builder 模式的构造

StuApi api = Feign.builder() //创建feign的构建者 .encoder(new JacksonEncoder()) //JSON编码 .decoder(new JacksonDecoder()) //JSON解码 .options(new Request.Options(1000, 3500)) //设置超时 .retryer(new Retryer.Default(5000, 5000, 3)) //设置重试 .target(StuApi.class, "http://127.0.0.1:8080"); //设置代理的接口以及目标地址

然后可以通过 api.xxx 进行服务调用。

这里请不要忘记引入相关的引用,相关的 pom.xml

<!--feign的客户端--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> <version>9.7.0</version> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</artifactId> <version>9.7.0</version> </dependency> <!--因为使用的是jackson 序列化,所以引入此包--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-jackson</artifactId> <version>9.7.0</version> </dependency> <!--客户端使用的okhttp所以引入此包--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> <version>9.7.0</version> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.10.0</version> </dependency>

其他相关的引用可以从此处查看:

http://mvnrepository.com/artifact/io.github.openfeign

总结

通过 Feign 的方式进行 HTTP 调用真心很方便,如果有涉及到需要调用第三方提供 HTTP 接口的时候,不妨考虑下 Feign

积土成山,风雨兴焉。积水成渊,蛟龙生焉。

1 操作
mulyzhou 在 2021-01-06 17:19:41 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...