作者:元人部落\
起源:www.cnblogs.com/bryan31/p/13359376.html

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了

@Autowiredprivate MyClient myClient;@Overridepublic 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。

近期热文举荐:

1.600+ 道 Java面试题及答案整顿(2021最新版)

2.终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!

3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!