驽马十驾 驽马十驾

驽马十驾,功在不舍

目录
使用原生的Feign进行HTTP调用
/  

使用原生的Feign进行HTTP调用

前言

在最开始学习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

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