在最开始学习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);
}
}
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("Content-Type: application/json")
@Headers({"Content-Type: application/json", "Accept: application/json"})
实际测试后发现,只要是@RestController修饰的提供者,不管请求和响应类型,直接采用第二种都可以。
但是如果请求和响应都是json,那么如果不些@Headers这个注解,肯定报错。比如后续的2 3 4这3个API.
通过@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
。