常用的http請求方式(第三方HTTP接口請求利器)
2023-04-20 14:01:47 1
推薦一款非常不錯的 HTTP 請求發包工具: forest。
介紹Java 日常開發中,肯定會經常遇到 HTTP 遠程調用的情況,微服務場景下,有 feign/open-feign 這樣的非常簡潔的第三方方案。
但是在調用第三方服務的情況下,一般會選擇 Apache 的 HttpClient、OkHttp 這樣的第三方庫 或者 JDK11 提供的 java.net.http.HttpClient;但是這些庫都需要寫不少代碼,使用比較繁瑣。
今天要推薦的 forest 用起來和 feign 非常類似, 最直觀的感受如下:
簡單: 只需要寫接口,不需要寫實現(forest 替你自動生成了繁瑣的實現)。擴展性強: 底層的實現可以由你自己指定是使用 OkHttp 還是其他的實現。模板變量異步請求攔截器自定義轉換器架構forest 的架構圖如下(圖片來自官網):
forest架構圖
可以將 forest 和 JDBC 類比:
JDBC 定義了標準,用戶只需要針對 JDBC 的 API 接口編程,底層實現可以自由切換forest 也定義了自己的 HTTP 請求,用戶只需要針對 forest 接口編程,底層實現可以自由切換(雖然目前的選擇就OkHttp和ApacheHttpClient兩種)聲明式接口簡單示例這裡就以 spring-boot 項目為例來簡單演示 forest 的用法。
依賴com.dtflys.forest forest-Spring-boot-starter 1.5.25
包掃描配置// 1.5.1以後版本可以跳過此步,不需要 @ForestScan 註解來指定掃描的包範圍@ForestScan(basePackages = "com.example.demo.forestdemo.client")@SpringBootApplicationpublic class ForestDemoApplication { public static void main(String[] args) { SpringApplication.run(ForestDemoApplication.class, args); }}
定義接口public interface HttpCallService { @Get("https://github.com/dromara/forest") String helloForest; @Get("https://ditu.amap.com/service/regeo?longitude={0}&latitude={1}") Map getLocation(String longitude, String latitude);}
然後就可以直接調用接口了,不需要寫實現。
@SpringBootTestclass HttpCallServiceTest { @Autowired private HttpCallService httpCallService; @Test void helloForest { final String response = httpCallService.helloForest; System.out.println(response); } @Test void getLocation throws JsonProcessingException { final Map location = this.httpCallService.getLocation("121.369", "31.258"); System.out.println(new ObjectMapper.writeValueAsString(location)); }}
編程式接口簡單示例如果你不想定義接口,就想直接發 HTTP 請求,forest 也提供了快捷接口:
class HttpCallServiceTest { @Test void shortcutMethodTest { // get 請求 https://www.baidu.com // 然後將響應結果轉為字符串 final String response = Forest.get("https://www.baidu.com").executeAsString; System.out.println(response); }}
說個題外話: 個人感覺,在快捷接口(編程式接口)方面,還是 JDK11 提供的 java.net.http.HttpClient 的功能更加豐富,下面是 JDK11 的 HttpClient 實現的和上面例子一樣的功能的寫法:
public class MainTest { static final executorService EXECUTOR = Executors.newFixedThreadPool(16); @Test public void testGet throws IOException, InterruptedException, URISyntaxException { final HttpClient httpClient = HttpClient .newBuilder .executor(EXECUTOR) .build; final Httprequest httpRequest = HttpRequest.newBuilder .uri(new URI("https://www.baidu.com")) .header("User-Agent", "jdk 9 http client") .GET .build; final HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString); System.out.println(httpResponse.statusCode); System.out.println(httpResponse.body); } @Test public void testAsyncGet throws URISyntaxException { final HttpClient httpClient = HttpClient .newBuilder .executor(EXECUTOR) .build; final HttpRequest request = HttpRequest.newBuilder .uri(new URI("https://www.baidu.com")) .GET .build; final CompletableFuture<HttpResponse> response = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString); response.whenComplete((resp, t) -> { if (t != null) { t.printStackTrace; } else { System.out.println(resp.body); System.out.println(resp.statusCode); } }).join; }}
個人感覺 forest 的聲明式接口這點是非常簡潔易用的。
其他各種特性建議直接看官方文檔: https://forest.dtflyx.com/
,