前言
在最开始学习 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
这个注解需要指明请求的类型和响应类型。
- 如果只有响应的是 json,那么如第一个 api 所示
@Headers("Content-Type: application/json")
- 如果请求和相应都是 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
。
积土成山,风雨兴焉。积水成渊,蛟龙生焉。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于