Forest - 轻量级HTTP客户端API框架,该丢弃HttpClient了 深碍√TFBOYSˉ_ 2023-01-14 14:57 475阅读 0赞 # 一、前言 # 最近在码云上扒了一波,发现了一个非常优秀的开源的轻量级`HTTP`客户端`API`框架`Forest`,这款`API`框架让`Java`发送`HTTP/HTTPS`请求不再难,他比原先了`OkHttp`和`HttpClient`更高层,以前在调用一个第三方外部API接口时,你可能需要使用`HTTPClient`或者`OkHttp`工具来实现,封装一个`HTTPClientUtil`工具类,工具类中封装一些`Post/Get`请求,那么现在你完全不需要这么做了,使用`Forest`框架只需要在你的接口上面加一个注解即可实现第三方API接口的调用。 # 二、Forest简介 # ## 1.简介 ## 轻量级HTTP客户端API框架,让Java发送HTTP/HTTPS请求不再难。它比OkHttp和HttpClient更高层,是封装调用第三方restful api client接口的好帮手,是retrofit和feign之外另一个选择。 * **项目主页:** [http://forest.dtflyx.com/][http_forest.dtflyx.com] * **中文文档:** [http://forest.dtflyx.com/docs/][http_forest.dtflyx.com] ## 2.什么是 Forest? ## orest 是一个开源的 Java HTTP 客户端框架,它能够将 HTTP 的所有请求信息(包括 URL、Header 以及 Body 等信息)绑定到您自定义的 Interface 方法上,能够通过调用本地接口方法的方式发送 HTTP 请求。 ## 3. 为什么使用 Forest? ## 使用 Forest 就像使用类似 Dubbo 那样的 RPC 框架一样,只需要定义接口,调用接口即可,不必关心具体发送 HTTP 请求的细节。同时将 HTTP 请求信息与业务代码解耦,方便您统一管理大量 HTTP 的 URL、Header 等信息。而请求的调用方完全不必在意 HTTP 的具体内容,即使该 HTTP 请求信息发生变更,大多数情况也不需要修改调用发送请求的代码。 ## 4.Forest 的工作原理 ## Forest 会将您定义好的接口通过动态代理的方式生成一个具体的实现类,然后组织、验证 HTTP 请求信息,绑定动态数据,转换数据形式,SSL 验证签名,调用后端 HTTP API(httpclient 等 API)执行实际请求,等待响应,失败重试,转换响应数据到 Java 类型等脏活累活都由这动态代理的实现类给包了。 请求发送方调用这个接口时,实际上就是在调用这个干脏活累活的实现类。 ## 5.Forest 的架构 ## ![architecture][] 我们讲 HTTP 发送请求的过程分为前端部分和后端部分,Forest 本身是处理前端过程的框架,是对后端 HTTP API 框架的进一步封装。 ### **前端部分:** ### 1. Forest 配置: 负责管理 HTTP 发送请求所需的配置。 2. Forest 注解: 用于定义 HTTP 发送请求的所有相关信息,一般定义在 interface 上和其方法上。 3. 动态代理: 用户定义好的 HTTP 请求的interface将通过动态代理产生实际执行发送请求过程的代理类。 4. 模板表达式: 模板表达式可以嵌入在几乎所有的 HTTP 请求参数定义中,它能够将用户通过参数或全局变量传入的数据动态 绑定到 HTTP 请求信息中。 5. 数据转换: 此模块将字符串数据和JSON或XML形式数据进行互转。目前 JSON 转换器支持Jackson、Fastjson、Gson三种,XML 支持JAXB一种。 6. 拦截器: 用户可以自定义拦截器,拦截指定的一个或一批请求的开始、成功返回数据、失败、完成等生命周期中的各个环节,以插入自定义的逻辑进行处理。 7. 过滤器: 用于动态过滤和处理传入 HTTP 请求的相关数据。 8. SSL: Forest 支持单向和双向验证的 HTTPS 请求,此模块用于处理 SSL 相关协议的内容。 ### **后端部分:** ### 后端为实际执行 HTTP 请求发送过程的第三方 HTTP API,目前支持okHttp3和httpclient两种后端 API。 Spring Boot Starter Forest:提供对Spring Boot的支持 ### 环境要求 ### * Forest 1.0.x 和 Forest 1.1.x 基于 JDK 1.7, Forest 1.2.x及以上版本基于 JDK 1.8 # 三、Forest有哪些特性? # * 以Httpclient和OkHttp为后端框架 * 通过调用本地方法的方式去发送Http请求, 实现了业务逻辑与Http协议之间的解耦 * 因为针对第三方接口,所以不需要依赖Spring Cloud和任何注册中心 * 支持所有请求方法:GET, HEAD, OPTIONS, TRACE, POST, DELETE, PUT, PATCH * 支持文件上传和下载 * 支持灵活的模板表达式 * 支持拦截器处理请求的各个生命周期 * 支持自定义注解 * 支持OAuth2验证 * 支持过滤器来过滤传入的数据 * 基于注解、配置化的方式定义Http请求 * 支持Spring和Springboot集成 * JSON字符串到Java对象的自动化解析 * XML文本到Java对象的自动化解析 * JSON、XML或其他类型转换器可以随意扩展和替换 * 支持JSON转换框架: Fastjson, Jackson, Gson * 支持JAXB形式的XML转换 * 可以通过OnSuccess和OnError接口参数实现请求结果的回调 * 配置简单,一般只需要@Request一个注解就能完成绝大多数请求的定义 * 支持异步请求调用 # 四、SpringBoot如何快速接入 # > 在官方的文档上明确介绍了有关Spring传统项目如何接入Forest,这里我直接以SpringBoot为例,都是一个道理,无非对于SpringBoot提供的是`xxx-spring-boot-starter`以开头的依赖`forest-spring-boot-starter`。 ## 1. 第一步:添加Maven依赖 ## 直接添加以下maven依赖即可: <dependency> <groupId>com.dtflys.forest</groupId> <artifactId>forest-spring-boot-starter</artifactId> <version>1.5.0</version> </dependency> ## 2. 第二步:创建一个`interface` ## package com.yoursite.client; import com.dtflys.forest.annotation.Request; import com.dtflys.forest.annotation.DataParam; public interface AmapClient { /** * 聪明的你一定看出来了@Get注解代表该方法专做GET请求 * 在url中的${0}代表引用第一个参数,${1}引用第二个参数 */ @Get("http://ditu.amap.com/service/regeo?longitude=${0}&latitude=${1}") public Map getLocation(String longitude, String latitude); } ## 3. 第三步:扫描接口 ## 在`Spring Boot`的配置类或者启动类上加上`@ForestScan`注解,并在`basePackages`属性里填上远程接口的所在的包名: @SpringBootApplication @Configuration @ForestScan(basePackages = "com.yoursite.client") public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } ## 4. 第四步:调用接口 ## // 注入接口实例 @Autowired private AmapClient amapClient; ... // 调用接口 Map result = amapClient.getLocation("121.475078", "31.223577"); System.out.println(result); ## 5. application.yml全局基本配置 ## forest: bean-id: config0 # 在spring上下文中bean的id, 默认值为forestConfiguration backend: okhttp3 # 后端HTTP API: okhttp3 max-connections: 1000 # 连接池最大连接数,默认值为500 max-route-connections: 500 # 每个路由的最大连接数,默认值为500 timeout: 3000 # 请求超时时间,单位为毫秒, 默认值为3000 connect-timeout: 3000 # 连接超时时间,单位为毫秒, 默认值为2000 retry-count: 1 # 请求失败后重试次数,默认为0次不重试 ssl-protocol: SSLv3 # 单向验证的HTTPS的默认SSL协议,默认为SSLv3 logEnabled: true # 打开或关闭日志,默认为true log-request: true # 打开/关闭Forest请求日志(默认为 true) log-response-status: true # 打开/关闭Forest响应状态日志(默认为 true) log-response-content: true # 打开/关闭Forest响应内容日志(默认为 false # 五、支持发送的请求类型 # ## 1. 请求类型:可支持(GET, POST, PUT, HEAD, OPTIONS, DELETE) ## * 使用POST方式 public interface MyClient { /** * 通过 @Request 注解的 type 参数指定 HTTP 请求的方式。 */ @Request( url = "http://localhost:8080/hello", type = "POST" ) String simplePost(); /** * 使用 @Post 注解,可以去掉 type = "POST" 这行属性 */ @Post("http://localhost:8080/hello") String simplePost(); /** * 使用 @PostRequest 注解,和上面效果等价 */ @PostRequest("http://localhost:8080/hello") String simplePost(); } 除了`GET`和`POST`,也可以指定成其他几种`HTTP` 请求方式(`PUT`, `HEAD`, `OPTIONS`, `DELETE`)。 其中`type`属性的大小写不敏感,写成`POST`和`post`效果相同。 * `GET`和`POST`大小写不敏感 // GET请求 @Request( url = "http://localhost:8080/hello", type = "get" ) String simpleGet(); // POST请求 @Request( url = "http://localhost:8080/hello", type = "post" ) String simplePost(); // PUT请求 @Request( url = "http://localhost:8080/hello", type = "put" ) String simplePut(); // HEAD请求 @Request( url = "http://localhost:8080/hello", type = "head" ) String simpleHead(); // Options请求 @Request( url = "http://localhost:8080/hello", type = "options" ) String simpleOptions(); // Delete请求 @Request( url = "http://localhost:8080/hello", type = "delete" ) String simpleDelete(); 另外,可以用`@GetRequest`, `@PostRequest`等注解代替`@Request`注解,这样就可以省去写`type`属性的麻烦了。 * 例如xxxRequest等价于xxx // GET请求 @Get("http://localhost:8080/hello") String simpleGet(); // GET请求 @GetRequest("http://localhost:8080/hello") String simpleGetRequest(); // POST请求 @Post("http://localhost:8080/hello") String simplePost(); // POST请求 @PostRequest("http://localhost:8080/hello") String simplePostRequest(); // PUT请求 @Put("http://localhost:8080/hello") String simplePut(); // PUT请求 @PutRequest("http://localhost:8080/hello") String simplePutRequest(); // HEAD请求 @HeadRequest("http://localhost:8080/hello") String simpleHead(); // Options请求 @Options("http://localhost:8080/hello") String simpleOptions(); // Options请求 @OptionsRequest("http://localhost:8080/hello") String simpleOptionsRequest(); // Delete请求 @Delete("http://localhost:8080/hello") String simpleDelete(); // Delete请求 @DeleteRequest("http://localhost:8080/hello") String simpleDeleteRequest(); 如上所示,请求类型是不是更一目了然了,代码也更短了。 `@Get`和`@GetRequest`两个注解的效果是等价的,`@Post`和`@PostRequest`、`@Put`和`@PutRequest`等注解也是同理。 # 六、支持的数据发送格式 # ## 1. 发送JSON数据 ## * **将对象参数解析为JSON字符串,并放在请求的Body进行传输 :** /** * 将对象参数解析为JSON字符串,并放在请求的Body进行传输 */ @Post("/register") public String registerUser(@JSONBody MyUser user); * **将Map类型参数解析为JSON字符串,并放在请求的Body进行传输 :** /** * 将Map类型参数解析为JSON字符串,并放在请求的Body进行传输 */ @Post("/test/json") public String postJsonMap(@JSONBody Map mapObj); * **直接传入一个JSON字符串,并放在请求的Body进行传输 :** /** * 直接传入一个JSON字符串,并放在请求的Body进行传输 */ @Post("/test/json") public String postJsonText(@JSONBody String jsonText); ## 2. 发送XML数据 ## /** * 将一个通过JAXB注解修饰过的类型对象解析为XML字符串 * 并放在请求的Body进行传输 */ @Post("/message") String sendXmlMessage(@XMLBody MyMessage message); /** * 直接传入一个XML字符串,并放在请求的Body进行传输 */ @Post("/test/xml") String postXmlBodyString(@XMLBody String xml); ## 3. 文件上传 ## /** * 用@DataFile注解修饰要上传的参数对象 * OnProgress参数为监听上传进度的回调函数 */ @Post("/upload") Map upload(@DataFile("file") String filePath, OnProgress onProgress); 可以用一个方法加`Lambda`同时解决文件上传和上传的进度监听 Map result = myClient.upload("D:\\TestUpload\\xxx.jpg", progress -> { System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%"); // 已上传百分比 if (progress.isDone()) { // 是否上传完成 System.out.println("-------- Upload Completed! --------"); } }); ## 4. 多文件批量上传 ## /** * 上传Map包装的文件列表,其中 ${_key} 代表Map中每一次迭代中的键值 */ @Post("/upload") ForestRequest<Map> uploadByteArrayMap(@DataFile(value = "file", fileName = "${_key}") Map<String, byte[]> byteArrayMap); /** * 上传List包装的文件列表,其中 ${_index} 代表每次迭代List的循环计数(从零开始计) */ @Post("/upload") ForestRequest<Map> uploadByteArrayList(@DataFile(value = "file", fileName = "test-img-${_index}.jpg") List<byte[]> byteArrayList); ## 5. 文件下载 ## 下载文件也是同样的简单 /** * 在方法上加上@DownloadFile注解 * dir属性表示文件下载到哪个目录 * OnProgress参数为监听上传进度的回调函数 * ${0}代表引用第一个参数 */ @Get("http://localhost:8080/images/xxx.jpg") @DownloadFile(dir = "${0}") File downloadFile(String dir, OnProgress onProgress); 调用下载接口以及监听下载进度的代码如下: File file = myClient.downloadFile("D:\\TestDownload", progress -> { System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%"); // 已下载百分比 if (progress.isDone()) { // 是否下载完成 System.out.println("-------- Download Completed! --------"); } }); ## 6.基本签名验证 ## @Post("/hello/user?username=${username}") @BasicAuth(username = "${username}", password = "bar") String send(@DataVariable("username") String username); ## 7. OAuth 2.0 ## @OAuth2( tokenUri = "/auth/oauth/token", clientId = "password", clientSecret = "xxxxx-yyyyy-zzzzz", grantType = OAuth2.GrantType.PASSWORD, scope = "any", username = "root", password = "xxxxxx" ) @Get("/test/data") String getData(); 等等特性,详细文档请看:[http://forest.dtflyx.com/][http_forest.dtflyx.com] # 七、详细文档请看:http://forest.dtflyx.com/ # [http_forest.dtflyx.com]: http://forest.dtflyx.com/ [architecture]: /images/20221022/00acadecba134019a28319878b7dbb4e.png
相关 Forest-极简的轻量级HTTP框架 是不是一想到要对接第三方系统接口就发愁,尤其是与其他系统有大量接口交互时,不得不应对各种请求方式、设置各种不同的头、不同的返回、需要权限或token验证等等,将头疼不已,即使有 ゞ 浴缸里的玫瑰/ 2024年03月02日 10:46/ 0 赞/ 24 阅读
相关 HttpClient Java客户端 文章目录 HttpClient Java客户端 建立使用HttpClient的环境 HttpGet请求 HttpGet带参请 青旅半醒/ 2023年10月10日 11:29/ 0 赞/ 52 阅读
相关 HTTP协议客户端之HttpClient的基本使用 HttpClient的基本使用 概述 > HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 心已赠人/ 2023年09月27日 15:59/ 0 赞/ 120 阅读
相关 该丢弃 HttpClient 了,这款轻量级 HTTP 客户端 API 框架很强! 一、Forest 1.1 业务需求 一般情况下是后端提供接口,前端调用,解决需求,但是有的时候为了方便,复用别人的接口(网上的,公共的第三方接口(短信、天气等)), 我就是我/ 2023年09月26日 15:56/ 0 赞/ 34 阅读
相关 Forest - 轻量级HTTP客户端API框架,该丢弃HttpClient了 一、前言 最近在码云上扒了一波,发现了一个非常优秀的开源的轻量级`HTTP`客户端`API`框架`Forest`,这款`API`框架让`Java`发送`HTTP/HTTP 深碍√TFBOYSˉ_/ 2023年01月14日 14:57/ 0 赞/ 476 阅读
相关 HTTP 客户端连接,选择 HttpClient 还是 OkHttp? > 开发者(KaiFaX) > > > 面向全栈工程师的开发者 > 专注于前端、Java/Python/Go/PHP的技术社区 来源:juejin.im/pos 小咪咪/ 2022年08月28日 02:58/ 0 赞/ 159 阅读
相关 一步步构建轻量级http-contract客户端 http-client-plus是一个类似于Feign一样的申明式ESB请求代理组件,使用ESB请求代理组件,面向SpringCloud微服务的,老的项目spring3.x也支 傷城~/ 2022年05月17日 07:16/ 0 赞/ 183 阅读
相关 apache httpclient cache 实现可缓存的http客户端 转自: [https://www.cnblogs.com/dehai/p/5063106.html][https_www.cnblogs.com_dehai_p_5063106 蔚落/ 2022年01月31日 01:47/ 0 赞/ 186 阅读
相关 适用于Spring Boot的轻量级 HTTP 客户端框架 ![7b0c1a80a932c1a737ec5fcec4eb4177.gif][] 在`SpringBoot`项目直接使用`okhttp`、`httpClient`或者`Re 逃离我推掉我的手/ 2021年09月07日 06:18/ 0 赞/ 294 阅读
还没有评论,来说两句吧...