偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Forest輕量級(jí)HTTP客戶端API框架,該丟棄HttpClient了

開(kāi)源
輕量級(jí)HTTP客戶端API框架,讓Java發(fā)送HTTP/HTTPS請(qǐng)求不再難。它比OkHttp和HttpClient更高層,是封裝調(diào)用第三方restful api client接口的好幫手,是retrofit和feign之外另一個(gè)選擇。

[[394925]]

一、前言

最近在碼云上扒了一波,發(fā)現(xiàn)了一個(gè)非常優(yōu)秀的開(kāi)源的輕量級(jí)HTTP客戶端API框架Forest,這款A(yù)PI框架讓Java發(fā)送HTTP/HTTPS請(qǐng)求不再難,他比原先了OkHttp和HttpClient更高層,以前在調(diào)用一個(gè)第三方外部API接口時(shí),你可能需要使用HTTPClient或者OkHttp工具來(lái)實(shí)現(xiàn),封裝一個(gè)HTTPClientUtil工具類(lèi),工具類(lèi)中封裝一些Post/Get請(qǐng)求,那么現(xiàn)在你完全不需要這么做了,使用Forest框架只需要在你的接口上面加一個(gè)注解即可實(shí)現(xiàn)第三方API接口的調(diào)用。

二、Forest簡(jiǎn)介

1.簡(jiǎn)介

輕量級(jí)HTTP客戶端API框架,讓Java發(fā)送HTTP/HTTPS請(qǐng)求不再難。它比OkHttp和HttpClient更高層,是封裝調(diào)用第三方restful api client接口的好幫手,是retrofit和feign之外另一個(gè)選擇。

  • 項(xiàng)目主頁(yè): http://forest.dtflyx.com/
  • 中文文檔: http://forest.dtflyx.com/docs/

2.什么是 Forest?

orest 是一個(gè)開(kāi)源的 Java HTTP 客戶端框架,它能夠?qū)?HTTP 的所有請(qǐng)求信息(包括 URL、Header 以及 Body 等信息)綁定到您自定義的 Interface 方法上,能夠通過(guò)調(diào)用本地接口方法的方式發(fā)送 HTTP 請(qǐng)求。

3. 為什么使用 Forest?

使用 Forest 就像使用類(lèi)似 Dubbo 那樣的 RPC 框架一樣,只需要定義接口,調(diào)用接口即可,不必關(guān)心具體發(fā)送 HTTP 請(qǐng)求的細(xì)節(jié)。同時(shí)將 HTTP 請(qǐng)求信息與業(yè)務(wù)代碼解耦,方便您統(tǒng)一管理大量 HTTP 的 URL、Header 等信息。而請(qǐng)求的調(diào)用方完全不必在意 HTTP 的具體內(nèi)容,即使該 HTTP 請(qǐng)求信息發(fā)生變更,大多數(shù)情況也不需要修改調(diào)用發(fā)送請(qǐng)求的代碼。

4.Forest 的工作原理

Forest 會(huì)將您定義好的接口通過(guò)動(dòng)態(tài)代理的方式生成一個(gè)具體的實(shí)現(xiàn)類(lèi),然后組織、驗(yàn)證 HTTP 請(qǐng)求信息,綁定動(dòng)態(tài)數(shù)據(jù),轉(zhuǎn)換數(shù)據(jù)形式,SSL 驗(yàn)證簽名,調(diào)用后端 HTTP API(httpclient 等 API)執(zhí)行實(shí)際請(qǐng)求,等待響應(yīng),失敗重試,轉(zhuǎn)換響應(yīng)數(shù)據(jù)到 Java 類(lèi)型等臟活累活都由這動(dòng)態(tài)代理的實(shí)現(xiàn)類(lèi)給包了。請(qǐng)求發(fā)送方調(diào)用這個(gè)接口時(shí),實(shí)際上就是在調(diào)用這個(gè)干臟活累活的實(shí)現(xiàn)類(lèi)。

5.Forest 的架構(gòu)

 

architecture

我們講 HTTP 發(fā)送請(qǐng)求的過(guò)程分為前端部分和后端部分,F(xiàn)orest 本身是處理前端過(guò)程的框架,是對(duì)后端 HTTP API 框架的進(jìn)一步封裝。

前端部分:

  1. Forest 配置:負(fù)責(zé)管理 HTTP 發(fā)送請(qǐng)求所需的配置。
  2. Forest 注解:用于定義 HTTP 發(fā)送請(qǐng)求的所有相關(guān)信息,一般定義在 interface 上和其方法上。
  3. 動(dòng)態(tài)代理:用戶定義好的 HTTP 請(qǐng)求的interface將通過(guò)動(dòng)態(tài)代理產(chǎn)生實(shí)際執(zhí)行發(fā)送請(qǐng)求過(guò)程的代理類(lèi)。
  4. 模板表達(dá)式:模板表達(dá)式可以嵌入在幾乎所有的 HTTP 請(qǐng)求參數(shù)定義中,它能夠?qū)⒂脩敉ㄟ^(guò)參數(shù)或全局變量傳入的數(shù)據(jù)動(dòng)態(tài) 綁定到 HTTP 請(qǐng)求信息中。
  5. 數(shù)據(jù)轉(zhuǎn)換:此模塊將字符串?dāng)?shù)據(jù)和JSON或XML形式數(shù)據(jù)進(jìn)行互轉(zhuǎn)。目前 JSON 轉(zhuǎn)換器支持Jackson、Fastjson、Gson三種,XML 支持JAXB一種。
  6. 攔截器:用戶可以自定義攔截器,攔截指定的一個(gè)或一批請(qǐng)求的開(kāi)始、成功返回?cái)?shù)據(jù)、失敗、完成等生命周期中的各個(gè)環(huán)節(jié),以插入自定義的邏輯進(jìn)行處理。
  7. 過(guò)濾器:用于動(dòng)態(tài)過(guò)濾和處理傳入 HTTP 請(qǐng)求的相關(guān)數(shù)據(jù)。
  8. SSL:Forest 支持單向和雙向驗(yàn)證的 HTTPS 請(qǐng)求,此模塊用于處理 SSL 相關(guān)協(xié)議的內(nèi)容。

后端部分:

后端為實(shí)際執(zhí)行 HTTP 請(qǐng)求發(fā)送過(guò)程的第三方 HTTP API,目前支持okHttp3和httpclient兩種后端 API。

Spring Boot Starter Forest:提供對(duì)Spring Boot的支持

環(huán)境要求

Forest 1.0.x 和 Forest 1.1.x 基于 JDK 1.7, Forest 1.2.x及以上版本基于 JDK 1.8

三、Forest有哪些特性?

  • 以Httpclient和OkHttp為后端框架
  • 通過(guò)調(diào)用本地方法的方式去發(fā)送Http請(qǐng)求, 實(shí)現(xiàn)了業(yè)務(wù)邏輯與Http協(xié)議之間的解耦
  • 因?yàn)獒槍?duì)第三方接口,所以不需要依賴Spring Cloud和任何注冊(cè)中心
  • 支持所有請(qǐng)求方法:GET, HEAD, OPTIONS, TRACE, POST, DELETE, PUT, PATCH
  • 支持文件上傳和下載
  • 支持靈活的模板表達(dá)式
  • 支持?jǐn)r截器處理請(qǐng)求的各個(gè)生命周期
  • 支持自定義注解
  • 支持OAuth2驗(yàn)證
  • 支持過(guò)濾器來(lái)過(guò)濾傳入的數(shù)據(jù)
  • 基于注解、配置化的方式定義Http請(qǐng)求
  • 支持Spring和Springboot集成
  • JSON字符串到Java對(duì)象的自動(dòng)化解析
  • XML文本到Java對(duì)象的自動(dòng)化解析
  • JSON、XML或其他類(lèi)型轉(zhuǎn)換器可以隨意擴(kuò)展和替換
  • 支持JSON轉(zhuǎn)換框架: Fastjson, Jackson, Gson
  • 支持JAXB形式的XML轉(zhuǎn)換
  • 可以通過(guò)OnSuccess和OnError接口參數(shù)實(shí)現(xiàn)請(qǐng)求結(jié)果的回調(diào)
  • 配置簡(jiǎn)單,一般只需要@Request一個(gè)注解就能完成絕大多數(shù)請(qǐng)求的定義
  • 支持異步請(qǐng)求調(diào)用

四、SpringBoot如何快速接入

在官方的文檔上明確介紹了有關(guān)Spring傳統(tǒng)項(xiàng)目如何接入Forest,這里我直接以SpringBoot為例,都是一個(gè)道理,無(wú)非對(duì)于SpringBoot提供的是xxx-spring-boot-starter以開(kāi)頭的依賴forest-spring-boot-starter。

1. 第一步:添加Maven依賴

直接添加以下maven依賴即可:

  1. <dependency> 
  2.     <groupId>com.dtflys.forest</groupId> 
  3.     <artifactId>forest-spring-boot-starter</artifactId> 
  4.     <version>1.5.0</version> 
  5. </dependency> 

2. 第二步:創(chuàng)建一個(gè)interfacepackage

  1. package com.yoursite.client; 
  2.  
  3. import com.dtflys.forest.annotation.Request; 
  4. import com.dtflys.forest.annotation.DataParam; 
  5.  
  6. public interface AmapClient { 
  7.  
  8.     /** 
  9.      * 聰明的你一定看出來(lái)了@Get注解代表該方法專(zhuān)做GET請(qǐng)求 
  10.      * 在url中的${0}代表引用第一個(gè)參數(shù),${1}引用第二個(gè)參數(shù) 
  11.      */ 
  12.     @Get("http://ditu.amap.com/service/regeo?longitude=${0}&latitude=${1}"
  13.     public Map getLocation(String longitude, String latitude); 
  14.      

3. 第三步:掃描接口

在Spring Boot的配置類(lèi)或者啟動(dòng)類(lèi)上加上@ForestScan注解,并在basePackages屬性里填上遠(yuǎn)程接口的所在的包名:

  1. @SpringBootApplication 
  2. @Configuration 
  3. @ForestScan(basePackages = "com.yoursite.client"
  4. public class MyApplication { 
  5.   public static void main(String[] args) { 
  6.       SpringApplication.run(MyApplication.class, args); 
  7.    } 

4. 第四步:調(diào)用接口

  1. // 注入接口實(shí)例 
  2. @Autowired 
  3. private AmapClient amapClient; 
  4. ... 
  5. // 調(diào)用接口 
  6. Map result = amapClient.getLocation("121.475078""31.223577"); 
  7. System.out.println(result); 

5. application.yml全局基本配置

  1. forest: 
  2.   bean-id: config0 # 在spring上下文中bean的id, 默認(rèn)值為forestConfiguration 
  3.   backend: okhttp3 # 后端HTTP API:okhttp3 
  4.   max-connections: 1000 # 連接池最大連接數(shù),默認(rèn)值為500 
  5.   max-route-connections: 500 # 每個(gè)路由的最大連接數(shù),默認(rèn)值為500 
  6.   timeout: 3000 # 請(qǐng)求超時(shí)時(shí)間,單位為毫秒, 默認(rèn)值為3000 
  7.   connect-timeout: 3000 # 連接超時(shí)時(shí)間,單位為毫秒, 默認(rèn)值為2000 
  8.   retry-count: 1 # 請(qǐng)求失敗后重試次數(shù),默認(rèn)為0次不重試 
  9.   ssl-protocol: SSLv3 # 單向驗(yàn)證的HTTPS的默認(rèn)SSL協(xié)議,默認(rèn)為SSLv3 
  10.   logEnabled: true # 打開(kāi)或關(guān)閉日志,默認(rèn)為true 
  11.   log-request: true # 打開(kāi)/關(guān)閉Forest請(qǐng)求日志(默認(rèn)為 true) 
  12.   log-response-status: true # 打開(kāi)/關(guān)閉Forest響應(yīng)狀態(tài)日志(默認(rèn)為 true) 
  13.   log-response-content: true # 打開(kāi)/關(guān)閉Forest響應(yīng)內(nèi)容日志(默認(rèn)為 false 

五、支持發(fā)送的請(qǐng)求類(lèi)型

1. 請(qǐng)求類(lèi)型:可支持(GET, POST, PUT, HEAD, OPTIONS, DELETE)使用POST方式

  1. public interface MyClient { 
  2.  
  3.     /** 
  4.      * 通過(guò) @Request 注解的 type 參數(shù)指定 HTTP 請(qǐng)求的方式。 
  5.      */ 
  6.     @Request( 
  7.             url = "http://localhost:8080/hello"
  8.             type = "POST" 
  9.     ) 
  10.     String simplePost(); 
  11.  
  12.     /** 
  13.      * 使用 @Post 注解,可以去掉 type = "POST" 這行屬性 
  14.      */ 
  15.     @Post("http://localhost:8080/hello"
  16.     String simplePost(); 
  17.  
  18.     /** 
  19.      * 使用 @PostRequest 注解,和上面效果等價(jià) 
  20.      */ 
  21.     @PostRequest("http://localhost:8080/hello"
  22.     String simplePost(); 
  23.  

除了GET和POST,也可以指定成其他幾種HTTP 請(qǐng)求方式(PUT, HEAD, OPTIONS, DELETE)。

其中type屬性的大小寫(xiě)不敏感,寫(xiě)成POST和post效果相同。

  • GET和POST大小寫(xiě)不敏感
  1. // GET請(qǐng)求 
  2. @Request( 
  3.         url = "http://localhost:8080/hello"
  4.         type = "get" 
  5. String simpleGet(); 
  6.  
  7. // POST請(qǐng)求 
  8. @Request( 
  9.         url = "http://localhost:8080/hello"
  10.         type = "post" 
  11. String simplePost(); 
  12.  
  13. // PUT請(qǐng)求 
  14. @Request( 
  15.         url = "http://localhost:8080/hello"
  16.         type = "put" 
  17. String simplePut(); 
  18.  
  19. // HEAD請(qǐng)求 
  20. @Request( 
  21.         url = "http://localhost:8080/hello"
  22.         type = "head" 
  23. String simpleHead(); 
  24.  
  25. // Options請(qǐng)求 
  26. @Request( 
  27.         url = "http://localhost:8080/hello"
  28.         type = "options" 
  29. String simpleOptions(); 
  30.  
  31. // Delete請(qǐng)求 
  32. @Request( 
  33.         url = "http://localhost:8080/hello"
  34.         type = "delete" 
  35. String simpleDelete(); 

另外,可以用@GetRequest, @PostRequest等注解代替@Request注解,這樣就可以省去寫(xiě)type屬性的麻煩了。

  • 例如xxxRequest等價(jià)于xxx
  1. // GET請(qǐng)求 
  2. @Get("http://localhost:8080/hello"
  3. String simpleGet(); 
  4.  
  5. // GET請(qǐng)求 
  6. @GetRequest("http://localhost:8080/hello"
  7. String simpleGetRequest(); 
  8.    
  9. // POST請(qǐng)求 
  10. @Post("http://localhost:8080/hello"
  11. String simplePost(); 
  12.  
  13. // POST請(qǐng)求 
  14. @PostRequest("http://localhost:8080/hello"
  15. String simplePostRequest(); 
  16.  
  17. // PUT請(qǐng)求 
  18. @Put("http://localhost:8080/hello"
  19. String simplePut(); 
  20.  
  21. // PUT請(qǐng)求 
  22. @PutRequest("http://localhost:8080/hello"
  23. String simplePutRequest(); 
  24.  
  25. // HEAD請(qǐng)求 
  26. @HeadRequest("http://localhost:8080/hello"
  27. String simpleHead(); 
  28.  
  29.  
  30. // Options請(qǐng)求 
  31. @Options("http://localhost:8080/hello"
  32. String simpleOptions(); 
  33.  
  34. // Options請(qǐng)求 
  35. @OptionsRequest("http://localhost:8080/hello"
  36. String simpleOptionsRequest(); 
  37.  
  38. // Delete請(qǐng)求 
  39. @Delete("http://localhost:8080/hello"
  40. String simpleDelete(); 
  41.  
  42. // Delete請(qǐng)求 
  43. @DeleteRequest("http://localhost:8080/hello"
  44. String simpleDeleteRequest(); 

如上所示,請(qǐng)求類(lèi)型是不是更一目了然了,代碼也更短了。

@Get和@GetRequest兩個(gè)注解的效果是等價(jià)的,@Post和@PostRequest、@Put和@PutRequest等注解也是同理。

六、支持的數(shù)據(jù)發(fā)送格式

1. 發(fā)送JSON數(shù)據(jù)

  • 將對(duì)象參數(shù)解析為JSON字符串,并放在請(qǐng)求的Body進(jìn)行傳輸 :
  1. /** 
  2.  * 將對(duì)象參數(shù)解析為JSON字符串,并放在請(qǐng)求的Body進(jìn)行傳輸 
  3.  */ 
  4. @Post("/register"
  5. public String registerUser(@JSONBody MyUser user); 
  • 將Map類(lèi)型參數(shù)解析為JSON字符串,并放在請(qǐng)求的Body進(jìn)行傳輸 :
  1. /** 
  2.  * 將Map類(lèi)型參數(shù)解析為JSON字符串,并放在請(qǐng)求的Body進(jìn)行傳輸 
  3.  */ 
  4. @Post("/test/json"
  5. public String postJsonMap(@JSONBody Map mapObj); 
  • 直接傳入一個(gè)JSON字符串,并放在請(qǐng)求的Body進(jìn)行傳輸 :
  1. /** 
  2.  * 直接傳入一個(gè)JSON字符串,并放在請(qǐng)求的Body進(jìn)行傳輸 
  3.  */ 
  4. @Post("/test/json"
  5. public String postJsonText(@JSONBody String jsonText); 

2. 發(fā)送XML數(shù)據(jù)

  1. /** 
  2.  * 將一個(gè)通過(guò)JAXB注解修飾過(guò)的類(lèi)型對(duì)象解析為XML字符串 
  3.  * 并放在請(qǐng)求的Body進(jìn)行傳輸 
  4.  */ 
  5. @Post("/message"
  6. String sendXmlMessage(@XMLBody MyMessage message); 
  7.  
  8. /** 
  9.  * 直接傳入一個(gè)XML字符串,并放在請(qǐng)求的Body進(jìn)行傳輸 
  10.  */ 
  11. @Post("/test/xml"
  12. String postXmlBodyString(@XMLBody String xml); 

3. 文件上傳

  1. /** 
  2.  * 用@DataFile注解修飾要上傳的參數(shù)對(duì)象 
  3.  * OnProgress參數(shù)為監(jiān)聽(tīng)上傳進(jìn)度的回調(diào)函數(shù) 
  4.  */ 
  5. @Post("/upload"
  6. Map upload(@DataFile("file") String filePath, OnProgress onProgress); 

可以用一個(gè)方法加Lambda同時(shí)解決文件上傳和上傳的進(jìn)度監(jiān)聽(tīng)

  1. Map result = myClient.upload("D:\\TestUpload\\xxx.jpg", progress -> { 
  2.     System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%");  // 已上傳百分比 
  3.     if (progress.isDone()) {   // 是否上傳完成 
  4.         System.out.println("--------   Upload Completed!   --------"); 
  5.     } 
  6. }); 

4. 多文件批量上傳

  1. /** 
  2.  * 上傳Map包裝的文件列表,其中 ${_key} 代表Map中每一次迭代中的鍵值 
  3.  */ 
  4. @Post("/upload"
  5. ForestRequest<Map> uploadByteArrayMap(@DataFile(value = "file", fileName = "${_key}") Map<String, byte[]> byteArrayMap); 
  6.  
  7. /** 
  8.  * 上傳List包裝的文件列表,其中 ${_index} 代表每次迭代List的循環(huán)計(jì)數(shù)(從零開(kāi)始計(jì)) 
  9.  */ 
  10. @Post("/upload"
  11. ForestRequest<Map> uploadByteArrayList(@DataFile(value = "file", fileName = "test-img-${_index}.jpg") List<byte[]> byteArrayList); 

5. 文件下載

下載文件也是同樣的簡(jiǎn)單

  1. /** 
  2.  * 在方法上加上@DownloadFile注解 
  3.  * dir屬性表示文件下載到哪個(gè)目錄 
  4.  * OnProgress參數(shù)為監(jiān)聽(tīng)上傳進(jìn)度的回調(diào)函數(shù) 
  5.  * ${0}代表引用第一個(gè)參數(shù) 
  6.  */ 
  7. @Get("http://localhost:8080/images/xxx.jpg"
  8. @DownloadFile(dir = "${0}"
  9. File downloadFile(String dir, OnProgress onProgress); 

調(diào)用下載接口以及監(jiān)聽(tīng)下載進(jìn)度的代碼如下:

  1. File file = myClient.downloadFile("D:\\TestDownload", progress -> { 
  2.     System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%");  // 已下載百分比 
  3.     if (progress.isDone()) {   // 是否下載完成 
  4.         System.out.println("--------   Download Completed!   --------"); 
  5.     } 
  6. }); 

6.基本簽名驗(yàn)證

  1. @Post("/hello/user?username=${username}"
  2. @BasicAuth(username = "${username}"password = "bar"
  3. String send(@DataVariable("username") String username); 

7. OAuth2.0

  1. @OAuth2( 
  2.         tokenUri = "/auth/oauth/token"
  3.         clientId = "password"
  4.         clientSecret = "xxxxx-yyyyy-zzzzz"
  5.         grantType = OAuth2.GrantType.PASSWORD
  6.         scope = "any"
  7.         username = "root"
  8.         password = "xxxxxx" 
  9. @Get("/test/data"
  10. String getData(); 

等等特性,詳細(xì)文檔請(qǐng)看:http://forest.dtflyx.com/

七、詳細(xì)文檔請(qǐng)看:http://forest.dtflyx.com/

 

責(zé)任編輯:姜華 來(lái)源: Thinking曹
相關(guān)推薦

2025-06-09 02:11:00

2020-03-24 15:15:29

HttpClientOkHttpJava

2022-03-08 13:46:22

httpClientHTTP前端

2022-05-16 07:37:58

SQL 編輯器數(shù)據(jù)庫(kù)管理工具

2024-05-09 08:30:57

OkHttpHTTP客戶端

2012-07-18 10:09:55

輕量級(jí)移動(dòng)客戶端開(kāi)發(fā)類(lèi)庫(kù)

2012-11-28 11:05:42

IBMdW

2012-09-19 14:27:16

Worklight

2021-05-21 10:48:09

http語(yǔ)言開(kāi)發(fā)

2009-06-12 19:18:08

REST客戶端框架JavaScript

2021-10-18 05:00:38

語(yǔ)言GoRequestHTTP

2020-11-11 12:13:59

JS

2022-08-10 12:21:07

PythonWebBottle

2023-06-27 16:42:18

Tinygrad深度學(xué)習(xí)工具

2025-03-07 08:57:46

HTTP客戶端框架

2021-09-22 15:46:29

虛擬桌面瘦客戶端胖客戶端

2011-08-17 10:10:59

2013-06-20 10:28:39

MVVM框架avalon架構(gòu)

2024-10-16 08:51:57

2024-11-21 16:37:30

客戶端業(yè)務(wù)解耦框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)