乐趣区

一款直击痛点的优秀http框架让我超高效率完成了和第三方接口的对接

1. 背景

因为业务关系,要和许多不同第三方公司进行对接。这些服务商都提供基于 http 的 api。然而每家公司提供 api 具体细节差异很大。有的基于 RESTFUL 标准,有的基于传统的 http 标准;有的须要在 header 里搁置签名,有的须要 SSL 的双向认证,有的只须要 SSL 的单向认证;有的以 JSON 形式进行序列化,有的以XML 形式进行序列化。相似于这样细节的差异太多了。

不同的公司 API 标准不一样,这很失常。然而对于我来说,我如果想要代码变得优雅。我就必须解决一个痛点:

不同服务商 API 那么多的差别点,如何能力保护一套不波及业务的公共 http 调用套件。最好通过配置或者简略的参数就能辨别开来。进行不便的调用?

我当然晓得有很多优良的赫赫有名的 http 开源框架能够实现任何模式的 http 调用,在多年的开发教训中我都有应用过。比方 apachehttpClient包,十分优良的Okhttpjersey client

这些 http 开源框架的接口应用相对来说,都不太一样。不论选哪个,在我这个场景里来说,我都不心愿在调用每个第三方的 http api 时写上一堆 http 调用代码。

所以,在这个场景里,我得对每种不同的 http api 进行封装。这样的代码能力更加优雅,业务代码和 http 调用逻辑耦合度更低。

惋惜,我比拟懒。一来感觉封装起来比拟费时间,二来觉对封装这种底层 http 调用来说,应该有更好的抉择。不想本人再去造轮子。

于是,我发现了一款优良的开源 http 框架,能屏蔽不同细节 http api 所带来的所有差别。能通过简略的配置像调用 rpc 框架一样的去实现极为简单的 http 调用。

Forest

https://gitee.com/dt_flys/forest

2. 上手

Forest反对了 Springboot 的主动拆卸,所以只须要引入一个依赖就行

<dependency>
  <groupId>com.dtflys.forest</groupId>
  <artifactId>spring-boot-starter-forest</artifactId>
  <version>1.3.0</version>
</dependency>

定义本人的接口类

public interface MyClient {@Request(url = "http://baidu.com")
    String simpleRequest();

    @Request(
            url = "http://ditu.amap.com/service/regeo",
            dataType = "json"
    )
    Map getLocation(@DataParam("longitude") String longitude, @DataParam("latitude") String latitude);
  
}

在启动类里配置代理接口类的扫描包

@SpringBootApplication
@ForestScan(basePackages = "com.example.demo.forest")
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);
    }
}

这时候,你就能够从 spring 容器中注入你的代理接口,像调用本地办法一样去调用 http 的 api 了

@Autowired
private MyClient myClient;

@Override
public void yourMethod throws Exception {Map result = myClient.getLocation("124.730329","31.463683");
    System.out.println(JSON.toJSONString(result,true));
}

日志打印,Forest打印了外部所用的 http 框架,和理论申请 url 和返回。当然日志能够通过配置去管制开关。

3. 特点

我感觉对于尤其是做对接第三方 api 的开发同学来说,这款开源框架能帮你进步很多效率。

Forest 底层封装了 2 种不同的 http 框架:Apache httpClientOKhttp。所以这个开源框架并没有对底层实现进行反复造轮子,而是在易用性下面下足了功夫。

我用 Forest 最终实现了和多个服务商 api 对接的我的项目,这些格调迥异的 API,我仅用了 1 个小时工夫就把他们转化为了本地办法。而后我的项目顺利上线。

Forest作为一款更加高层的 http 框架,其实你并不需要写很多代码,大多数时候,你仅通过一些配置就能实现 http 的本地化调用。而这个框架所能笼罩的面,却十分之广,满足你绝大多数的 http 调用申请。

Forest有以下特点:

  • HttpclientOkHttp为后端框架
  • 通过调用本地办法的形式去发送 Http 申请, 实现了业务逻辑与 Http 协定之间的解耦
  • 相比 Feign 更轻量,不依赖 Spring Cloud 和任何注册核心
  • 反对所有申请办法:GET, HEAD, OPTIONS, TRACE, POST, DELETE, PUT, PATCH
  • 反对灵便的模板表达式
  • 反对过滤器来过滤传入的数据
  • 基于注解、配置化的形式定义 Http 申请
  • 反对 SpringSpringboot集成
  • 实现 JSONXML的序列化和反序列化
  • 反对 JSON 转换框架: Fastjson, Jackson, Gson
  • 反对 JAXB 模式的 XML 转换
  • 反对 SSL 的单向和双向加密
  • 反对 http 连接池的设定
  • 能够通过 OnSuccessOnError接口参数实现申请后果的回调
  • 配置简略,个别只须要 @Request 一个注解就能实现绝大多数申请的定义
  • 反对异步申请调用

4. 两个很棒的性能

这里不对应用形式和配置形式一一形容,有趣味的能够去浏览具体文档:

https://dt_flys.gitee.io/forest

这里只想剖析这个框架 2 个我认为比拟好的性能

4.1 模板表达式和参数的映射绑定性能


模板表达式在应用的时候特地不便,举个栗子

@Request(url = "${0}/send?un=${1}&pw=${2}&ph=${3}&ct=${4}",
    type = "get",
    dataType = "json"
)
public Map send(
    String base,
    String userName,
    String password,
    String phone,
    String content
);

上述是用序号下标进行取值,也能够通过名字进行取值:


@Request(url = "${base}/send?un=${un}&pw=${pw}&ph=${3}&ct=${ct}",
    type = "get",
    dataType = "json"
)
public Map send(@DataVariable("base") String base,
    @DataVariable("un") String userName,
    @DataVariable("pw") String password,
    @DataVariable("ph") String phone,
    @DataVariable("ct") String content
);

甚至于能够这样简化写:

@Request(url = "${base}/send",
    type = "get",
    dataType = "json"
)
public Map send(@DataVariable("base") String base,
    @DataParam("un") String userName,
    @DataParam("pw") String password,
    @DataParam("ph") String phone,
    @DataParam("ct") String content
);

以上三种写法是等价的

当然你也能够把参数绑定到 header 和 body 里去,你甚至于能够用一些表达式简略的把对象序列化成 json 或者 xml:

@Request(url = "${base}/pay",
      contentType = "application/json",
    type = "post",
    dataType = "json",
    headers = {"Authorization: ${1}"},
    data = "${json($0)}"
)
public PayResponse pay(PayRequest request, String auth);

当然数据绑定这块详情请参阅文档

4.2 对 HTTPS 的反对

以前用其余 http 框架解决 https 的时候,总感觉特地麻烦,尤其是双向证书。每次碰到问题也只能去 baidu。而后依据他人的教训来批改本人的代码。

Forest对于这方面也想的很周到,底层完满封装了对 https 单双向证书的反对。也是只有通过简略的配置就能迅速实现。举个双向证书栗子:

@Request(url = "${base}/pay",
      contentType = "application/json",
    type = "post",
    dataType = "json",
      keyStore = "pay-keystore",
      data = "${json($0)}"
)
public PayResponse pay(PayRequest request);

其中 pay-keystore 对应着 application.yml 里的ssl-key-stores

forest:
  ...
  ssl-key-stores:
    - id: pay-keystore
      file: test.keystore
      keystore-pass: 123456
      cert-pass: 123456
      protocols: SSLv3

这样设置,就 ok 了,剩下的,就是本地代码模式的调用了。

5. 最初

Forest有很多其余的性能设定,如果感兴趣的同学还请认真去浏览文档和示例。

然而我想说的是,置信看到这里,很多人肯定会说,这不就是 Feign 吗?

我在开发 Spring Cloud 我的项目的时候,也用过一段时间 Feign,个人感觉Forest 确实在配置和用法上和 Feign 的设计很像,但 Feign 的角色更多是作为 Spring Cloud 生态里的一个成员。充当 RPC 通信的角色,其承当的不仅是 http 通信,还要对注册核心下发的调用地址进行负载平衡。

Forest 这个开源我的项目其定位则是一个高阶的 http 工具,主打敌对和易用性。从应用角度登程,个人感觉 Forest 配置性更加简略间接。提供的很多性能也能解决很多人的痛点。

开源精力难能可贵,好的开源须要大家的添砖加瓦和反对。心愿这篇文章能给大家在抉择 http 客户端框架时带来一个新的抉择:Forest

6. 分割作者

微信关注「jishuyuanren」获取更多技术干货

退出移动版