java運行jar包參數,JDK 之 HttpClient(jdk11)

 2023-10-09 阅读 26 评论 0

摘要:HttpClient 簡介 java.net.http.HttpClient 是 jdk11 中正式啟用的一個 http 工具類(其實早在 jdk9 的時候就已經存在了,只是處于孵化期),官方寓意為想要取代 HttpURLConnection 和 Apache HttpClient 等比較古老的開發工具。 新增的 HttpClient 截止到目前(201

HttpClient 簡介

java.net.http.HttpClient 是 jdk11 中正式啟用的一個 http 工具類(其實早在 jdk9 的時候就已經存在了,只是處于孵化期),官方寓意為想要取代 HttpURLConnection 和 Apache HttpClient 等比較古老的開發工具。

新增的 HttpClient 截止到目前(2019年3月)為止其實網絡資料還比較少,筆者只是根據一些博文和官方 Demo 自己摸索了一下,做了下總結。

java運行jar包參數,由于是 jdk11 中才正式使用的工具類,距離開發者還很遙遠,所以對于源碼筆者暫不打算深挖,淺淺的理解怎么使用就行

?

一、HttpClient在 Apache HttpClient 中,一般會創建一個 HttpClient 對象來作為門面。java.net.http.HttpClient 的邏輯也差不多,只是創建方式更加時髦了:

//創建 builder
HttpClient.Builder builder = HttpClient.newBuilder();//鏈式調用
HttpClient client = builder//http 協議版本 1.1 或者 2
.version(HttpClient.Version.HTTP_2) //.version(HttpClient.Version.HTTP_1_1)//連接超時時間,單位為毫秒
.connectTimeout(Duration.ofMillis(5000)) //.connectTimeout(Duration.ofMinutes(1))//連接完成之后的轉發策略
.followRedirects(HttpClient.Redirect.NEVER) //.followRedirects(HttpClient.Redirect.ALWAYS)//指定線程池
.executor(Executors.newFixedThreadPool(5))//認證,默認情況下 Authenticator.getDefault() 是 null 值,會報錯
//.authenticator(Authenticator.getDefault())//代理地址
//.proxy(ProxySelector.of(new InetSocketAddress("http://www.baidu.com", 8080)))//緩存,默認情況下 CookieHandler.getDefault() 是 null 值,會報錯
//.cookieHandler(CookieHandler.getDefault())//創建完成
.build();

java ssh客戶端,?

在 builder() 方法中,最終會調用到 HttpClientImpl 的構造器,完成 HttpClient 的創建工作:

?

    //HttpClientImpl.classprivate HttpClientImpl(HttpClientBuilderImpl builder,SingleFacadeFactory facadeFactory) {//CLIENT_IDS 是 AtomicLong 類型的變量,使用 incrementAndGet() 方法實現自增長的 idid = CLIENT_IDS.incrementAndGet();//記錄下存有 id 的字符串dbgTag = "HttpClientImpl(" + id + ")";//ssl 認證if (builder.sslContext == null) {try {sslContext = SSLContext.getDefault();} catch (NoSuchAlgorithmException ex) {throw new InternalError(ex);}} else {sslContext = builder.sslContext;}//線程池,沒有的話就默認創建一個Executor ex = builder.executor;if (ex == null) {ex = Executors.newCachedThreadPool(new DefaultThreadFactory(id));isDefaultExecutor = true;} else {isDefaultExecutor = false;}delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex);facadeRef = new WeakReference<>(facadeFactory.createFacade(this));//處理 http 2 的 client 類client2 = new Http2ClientImpl(this);‘//緩存操作cookieHandler = builder.cookieHandler;//超時時間connectTimeout = builder.connectTimeout;//轉發策略,默認為 NEVERfollowRedirects = builder.followRedirects == null ?Redirect.NEVER : builder.followRedirects;//代理設置this.userProxySelector = Optional.ofNullable(builder.proxy);this.proxySelector = userProxySelector.orElseGet(HttpClientImpl::getDefaultProxySelector);if (debug.on())debug.log("proxySelector is %s (user-supplied=%s)",this.proxySelector, userProxySelector.isPresent());//認證設置authenticator = builder.authenticator;//設置 http 協議版本if (builder.version == null) {version = HttpClient.Version.HTTP_2;} else {version = builder.version;}if (builder.sslParams == null) {sslParams = getDefaultParams(sslContext);} else {sslParams = builder.sslParams;}//連接線程池connections = new ConnectionPool(id);connections.start();timeouts = new TreeSet<>();//SelectorManager 本質上是 Thread 類的封裝//selmgr 會開啟一條線程,HttpClient 的主要邏輯運行在此線程中//所以說 HttpClient 是非阻塞的,因為并不跑在主線程中try {selmgr = new SelectorManager(this);} catch (IOException e) {throw new InternalError(e);}//設置為守護線程selmgr.setDaemon(true);filters = new FilterFactory();initFilters();assert facadeRef.get() != null;}

eclipse jdk1.8。?

?

主要是一些儲存操作,大致理解即可,不細究。

二、HttpRequest

the type java.util.Map$Entry、HttpRequest 是發起請求的主體配置:

//創建 builder
HttpRequest.Builder reBuilder = HttpRequest.newBuilder();//鏈式調用
HttpRequest request = reBuilder//存入消息頭
//消息頭是保存在一張 TreeMap 里的
.header("Content-Type", "application/json")//http 協議版本
.version(HttpClient.Version.HTTP_2)//url 地址
.uri(URI.create("http://openjdk.java.net/"))//超時時間
.timeout(Duration.ofMillis(5009))//發起一個 post 消息,需要存入一個消息體
.POST(HttpRequest.BodyPublishers.ofString("hello"))//發起一個 get 消息,get 不需要消息體
//.GET()//method(...) 方法是 POST(...) 和 GET(...) 方法的底層,效果一樣
//.method("POST",HttpRequest.BodyPublishers.ofString("hello"))//創建完成
.build();

?

三、發送

發起請求:

    HttpResponse<String> response =client.send(request, HttpResponse.BodyHandlers.ofString());
這是同步式的發起請求方式,先來看一下它的實現:
   public <T> HttpResponse<T> send(HttpRequest req, BodyHandler<T> responseHandler)throws IOException, InterruptedException{CompletableFuture<HttpResponse<T>> cf = null;try {
            //調用 sendAsync(...) 方法異步地完成主邏輯,并獲取 Futurecf = sendAsync(req, responseHandler, null, null);return cf.get();//這之后的所有代碼都是在進行異常捕捉,所以可以忽略} catch (InterruptedException ie) {if (cf != null )cf.cancel(true);throw ie;} catch (ExecutionException e) {final Throwable throwable = e.getCause();final String msg = throwable.getMessage();if (throwable instanceof IllegalArgumentException) {throw new IllegalArgumentException(msg, throwable);} else if (throwable instanceof SecurityException) {throw new SecurityException(msg, throwable);} else if (throwable instanceof HttpConnectTimeoutException) {HttpConnectTimeoutException hcte = new HttpConnectTimeoutException(msg);hcte.initCause(throwable);throw hcte;} else if (throwable instanceof HttpTimeoutException) {throw new HttpTimeoutException(msg);} else if (throwable instanceof ConnectException) {ConnectException ce = new ConnectException(msg);ce.initCause(throwable);throw ce;} else if (throwable instanceof IOException) {throw new IOException(msg, throwable);} else {throw new IOException(msg, throwable);}}}

?

本質上是使用了異步實現方法 sendAsync(…)。

在 Demo 中也可以直接使用:

    //返回的是 future,然后通過 future 來獲取結果CompletableFuture<String> future =client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body);//阻塞線程,從 future 中獲取結果String body = future.get();

  



轉載于:https://www.cnblogs.com/JiangWJ/p/10823112.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/134242.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息