由于业务关系,要和许多不一样第三方公司进行对接。这些服务商都提供基于http的api。可是每家公司提供api具体细节差异很大。有的基于RESTFUL
规范,有的基于传统的http规范;有的须要在header
里放置签名,有的须要SSL
的双向认证,有的只须要SSL
的单向认证;有的以JSON
方式进行序列化,有的以XML
方式进行序列化。相似于这样细节的差异太多了。java
不一样的公司API规范不同,这很正常。可是对于我来讲,我若是想要代码变得优雅。我就必须解决一个痛点:git
不一样服务商API那么多的差别点,如何才能维护一套不涉及业务的公共http调用套件。最好经过配置或者简单的参数就能区分开来。进行方便的调用?spring
我固然知道有不少优秀的大名鼎鼎的http开源框架能够实现任何形式的http调用,在多年的开发经验中我都有使用过。好比apache
的httpClient
包,很是优秀的Okhttp
,jersey client
。apache
这些http
开源框架的接口使用相对来讲,都不太同样。无论选哪一个,在我这个场景里来讲,我都不但愿在调用每一个第三方的http api时写上一堆http调用代码。json
因此,在这个场景里,我得对每种不一样的http api进行封装。这样的代码才能更加优雅,业务代码和http调用逻辑耦合度更低。后端
惋惜,我比较懒。一来以为封装起来比较费时间,二来觉对封装这种底层http调用来讲,应该有更好的选择。不想本身再去造轮子。api
因而,我发现了一款优秀的开源http框架,能屏蔽不一样细节http api所带来的全部差别。能经过简单的配置像调用rpc框架同样的去完成极为复杂的http调用。微信
Forestapp
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和返回。固然日志能够经过配置去控制开关。
我以为对于尤为是作对接第三方api的开发同窗来讲,这款开源框架能帮你提升不少效率。
Forest
底层封装了2种不一样的http框架:Apache httpClient
和OKhttp
。因此这个开源框架并无对底层实现进行重复造轮子,而是在易用性上面下足了功夫。
我用Forest
最终完成了和多个服务商api对接的项目,这些风格迥异的API,我仅用了1个小时时间就把他们转化为了本地方法。而后项目顺利上线。
Forest
做为一款更加高层的http框架,其实你并不须要写不少代码,大多数时候,你仅经过一些配置就能完成http的本地化调用。而这个框架所能覆盖的面,却很是之广,知足你绝大多数的http调用请求。
Forest
有如下特色:
Httpclient
和OkHttp
为后端框架Spring Cloud
和任何注册中心GET
, HEAD
, OPTIONS
, TRACE
, POST
, DELETE
, PUT
, PATCH
Http
请求Spring
和Springboot
集成JSON
和XML
的序列化和反序列化Fastjson
,Jackson
, Gson
JAXB
形式的XML
转换SSL
的单向和双向加密OnSuccess
和OnError
接口参数实现请求结果的回调@Request
一个注解就能完成绝大多数请求的定义这里不对使用方式和配置方式一一描述,有兴趣的能够去阅读详细文档:
https://dt_flys.gitee.io/forest
这里只想分析这个框架2个我认为比较好的功能
模板表达式在使用的时候特别方便,举个栗子
@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);
复制代码
固然数据绑定这块详情请参阅文档
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了,剩下的,就是本地代码形式的调用了。
Forest
有不少其余的功能设定,若是感兴趣的同窗还请仔细去阅读文档和示例。
可是我想说的是,相信看到这里,不少人必定会说,这不就是Feign
吗?
我在开发Spring Cloud
项目的时候,也用过一段时间Feign
,我的感受Forest
的确在配置和用法上和Feign
的设计很像,但Feign
的角色更可能是做为Spring Cloud
生态里的一个成员。充当RPC通讯的角色,其承担的不只是http通信,还要对注册中心下发的调用地址进行负载均衡。
而Forest
这个开源项目其定位则是一个高阶的http工具,主打友好和易用性。从使用角度出发,我的感受Forest
配置性更加简单直接。提供的不少功能也能解决不少人的痛点。
开源精神难能难得,好的开源须要你们的添砖加瓦和支持。但愿这篇文章能给你们在选择http客户端框架时带来一个新的选择:Forest
微信关注 jishuyuanren 获取更多技术干货