标签: java-http-client

Java 11 HttpClient - 什么是 HttpClient 与并发 HttpRequest 的最佳比率

在下面的示例中,我创建了一个 Java 11 httpClient,然后创建了多个并发 HttpRequest。

  1. 这是不好的做法吗?
  2. 每个 HttpRequest 都应该有自己的 HttpClient 吗?
  3. HttpClient 可以拥有的 HttpRequest 数量是否有上限?

代码

    private static void httpClientExample(){
    
    HttpClient httpClient = HttpClient.newHttpClient();

    System.out.println("TP1");

    var task1 = httpClient.sendAsync(HttpRequest.newBuilder()
            .uri(URI.create("https://www.bing.com/"))
            .build(), HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::uri).thenAccept(System.out::println);

    var task2 = httpClient.sendAsync(HttpRequest.newBuilder()
            .uri(URI.create("https://openjdk.java.net/"))
            .build(), HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::uri).thenAccept(System.out::println);
    
    var task3 = httpClient.sendAsync(HttpRequest.newBuilder()
            .uri(URI.create("https://www.google.co.uk/"))
            .build(), HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::uri).thenAccept(System.out::println);


    System.out.println("Requests Sent");

    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println("Main Thread Completed");
    }
Run Code Online (Sandbox Code Playgroud)

java java-http-client java-11

3
推荐指数
1
解决办法
917
查看次数

重新加载 java.net.http.HttpClient 的 SSLContext

我有一个程序,java.net.http.HttpClient它利用 Java 11 中引入的 来连接内部服务并向内部服务发送请求。这些服务相互验证,均提供内部 CA 颁发的证书。

例如,

SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
KeyManager keys = /* load our cert and key */;
TrustManager trust = /* load our trusted CA */;
sslContext.init(keys, trust, secureRandom);

HttpClient.Builder builder = HttpClient.newBuilder().sslContext(sslContext);
HttpClient client = builder.build();
Run Code Online (Sandbox Code Playgroud)

在我们的主机上,客户端的证书和私钥会定期轮换,比主机或应用程序有机会重新启动的频率更高。我希望能够在新的证书/密钥对仍在运行时重新加载它,但看不到任何方法可以做到这一点HttpClientSSLContext

构建完成后HttpClient,它仅提供一个sslContext()getter 来检索SSLContext. 似乎没有 API 来设置新的。

还有其他机制可以实现这一目标吗?

(我正在考虑类似于 Jetty 的SslContextFactory#reload(SSLContext)方法。)

java ssl mutual-authentication java-http-client

3
推荐指数
1
解决办法
6385
查看次数

如何向外部 Rest API 发出 Http Post 请求?

我是 Java spring 框架的新手,我需要一种从我的应用程序调用外部 Rest API 的方法。是否有任何“最佳实践”http 客户端可以满足我的需要?

java spring spring-boot java-http-client

2
推荐指数
1
解决办法
1万
查看次数

登录JDK11 HttpClient

JDK11引入了新的HTTP Client,具有许多传统java.net.HttpURLConnection类所缺乏的功能。我遇到的第一个问题是如何在新添加的 HTTP 客户端中正确启用日志记录?

java logging http java-http-client java-11

2
推荐指数
1
解决办法
3801
查看次数

带有 PATCH 方法的 Java 11 HttpRequest

我尝试使用 java 11HttpRequest使用 PATCH 方法调用 msgraph webservice:

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.net.URLEncoder;

import java.nio.charset.StandardCharsets;

import groovy.json.JsonSlurper;
import groovy.json.JsonOutput;

access_token = "my_token";

def url = 'https://graph.microsoft.com/v1.0/groups/group_id/drive/items/01P4AIIJ5QTIIAZ2FLEZBIZWRV6KEBIMM5/workbook/worksheets/%7B00000000-0001-0000-0000-000000000000%7D/range(address=\'A1\')'

HttpClient httpClient = HttpClient.newBuilder()
                                    .version(HttpClient.Version.HTTP_2)
                                    .build();

jsonPayloadString = '{"values":["blabla"]}';


jsonPayload = HttpRequest.BodyPublishers.ofString(jsonPayloadString.toString())

HttpRequest request = HttpRequest.newBuilder()
                                 .uri(URI.create(url))
                                 .PATCH(jsonPayload)
                                 .header("Content-Type", "application/json")
                                 .build();

HttpResponse response = httpClient.send(request,HttpResponse.BodyHandlers.ofString());

Run Code Online (Sandbox Code Playgroud)

错误 :

没有方法签名:jdk.internal.net.http.HttpRequestBuilderImpl.PATCH() 适用于参数类型:(jdk.internal.net.http.RequestPublishers$StringPublisher) 值:[jdk.internal.net.http.RequestPublishers$ StringPublisher@280a600b]

通话本身效果很好,例如在 Postman 中。但我不能让它在 groovy/java 中工作。

我以前使用过,HttpUrlConnection但它不支持 PATCH。实际上可以使用HttpRequest吗?

我在网上找不到任何使用 PATCH 方法的工作示例。

java groovy httprequest java-http-client java-11

2
推荐指数
1
解决办法
4060
查看次数

在 Java 11 及更高版本中使用 HttpClient 时如何跟进 HTTP 303 状态代码?

在使用java.net.http.HttpClientJava 11 及更高版本中的类时,如何告诉客户端遵循HTTP 303以到达重定向页面?

这是一个例子。维基百科提供了一个 REST URL,用于获取其内容的随机页面的摘要。该 URL 重定向到随机选择的页面的 URL。运行此代码时,我看到303调用HttpResponse#toString. 但我不知道如何告诉客户端类跟随新的 URL。

HttpClient client = HttpClient.newHttpClient();
HttpRequest request =
        HttpRequest
                .newBuilder()
                .uri( URI.create( "https://en.wikipedia.org/api/rest_v1/page/random/summary" ) )
                .build();
try
{
    HttpResponse < String > response = client.send( request , HttpResponse.BodyHandlers.ofString() );
    System.out.println( "response = " + response );   // ?? We can see the `303` status code.
    String body = response.body();
    System.out.println( "body = " + body );
}
catch ( …
Run Code Online (Sandbox Code Playgroud)

java http-redirect java-http-client

2
推荐指数
1
解决办法
302
查看次数

是否可以构建一个使用 SSL/TLS JAVA_OPTS 作为其 SSLContext 的 Java 11 HttpClient?

我知道HttpClientBuilder您可以使用 Apache调用useSystemProperties(),如果传递为,它将创建一个SSLContextjavax.net.ssl.keyStore(和信任库)配置的客户端JAVA_OPTS

try (CloseableHttpClient client = HttpClientBuilder.create().useSystemProperties.build()) {
  // If javax.net.ssl props are set, make requests that require client auth
  // Otherwise make regular requests
}
Run Code Online (Sandbox Code Playgroud)

我想用 Java 11 做一些类似的事情HttpClient。这样做的原因是在我的用例中,我将密钥存储和信任存储视为可选的,并且不必在我的代码中检查它们的存在会很好。基本上,我想SSLContext根据JAVA_OPTS它们是否存在来设置;否则只使用"Default"上下文

java ssl java-http-client java-11

1
推荐指数
1
解决办法
2219
查看次数

JDK11 HttpClient 相互 tls

我希望使用java 11 中提供新 HttpClient。不清楚如何进行双向 TLS(2 路身份验证,客户端和服务器都提供证书。)

有人可以提供一个使用 HttpClient 的双向 TLS 的例子吗?

java ssl java-http-client java-11

1
推荐指数
1
解决办法
1298
查看次数

使用 java.net.http.HttpClient 的 GOAWAY BItBucket API

使用java.net.http.HttpClient以下配置将请求发送到 BitBucket API:

var url = "https://bitbucket.org/api/2.0/repositories/asomov/snakeyaml/issues/377";

HttpClient client = HttpClient.newBuilder()
            .followRedirects(HttpClient.Redirect.ALWAYS)
            .version(HttpClient.Version.HTTP_2)
            .build();

HttpRequest request = HttpRequest.newBuilder()
                    .GET()
                    .uri(URI.create(url))
                    .setHeader("User-Agent", "Java 11 HttpClient Bot")
                    .timeout(Duration.ofSeconds(5))
                    .build();

HttpResponse<String> response = client.send(request,
                    HttpResponse.BodyHandlers.ofString());
Run Code Online (Sandbox Code Playgroud)

总是抛出以下异常:

java.io.IOException: /192.168.1.126:58337: GOAWAY received
    at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:576)
    at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:119)
Caused by: java.io.IOException: /192.168.1.126:58337: GOAWAY received
    at java.net.http/jdk.internal.net.http.Http2Connection.handleGoAway(Http2Connection.java:985)
    at java.net.http/jdk.internal.net.http.Http2Connection.handleConnectionFrame(Http2Connection.java:853)
    at java.net.http/jdk.internal.net.http.Http2Connection.processFrame(Http2Connection.java:724)
    at java.net.http/jdk.internal.net.http.frame.FramesDecoder.decode(FramesDecoder.java:155)
    at java.net.http/jdk.internal.net.http.Http2Connection$FramesController.processReceivedData(Http2Connection.java:232)
    at java.net.http/jdk.internal.net.http.Http2Connection.asyncReceive(Http2Connection.java:649)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.processQueue(Http2Connection.java:1275)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.runOrSchedule(Http2Connection.java:1293)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.onNext(Http2Connection.java:1319)
    at java.net.http/jdk.internal.net.http.Http2Connection$Http2TubeSubscriber.onNext(Http2Connection.java:1253)
    at …
Run Code Online (Sandbox Code Playgroud)

java http bitbucket httpclient java-http-client

1
推荐指数
1
解决办法
976
查看次数

上传时如何使用多路复用http2功能

上传多个文件时,使用多路复用 http2 功能应该会显着提高性能。

Java 有一个 httpclient,它原生支持 HTTP/2 协议,因此我尝试编写代码以供自己理解。

这项任务似乎并不像我最初想的那样容易,或者在另一方面,我似乎无法找到能够在上传中使用多路复用的服务器(如果存在)。

这是我写的代码,有人有想法吗?

HttpClient httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_2).build();
String url = "https://your-own-http2-server.com/incoming-files/%s";
Path basePath = Path.of("/path/to/directory/where/is/a/bunch/of/jpgs");

Function<Path, CompletableFuture<HttpResponse<String>>> handleFile = file -> {
    String currentUrl = String.format(url, file.getFileName().toString());
    try {
        HttpRequest request = HttpRequest.newBuilder()
                                         .uri(URI.create(currentUrl))
                                         .header("Content-Type", "image/jpeg")
                                         .PUT(HttpRequest.BodyPublishers.ofFile(file))
                                         .build();
        return httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
    } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
};

List<Path> files = Files.list(basePath).collect(toList());

files.parallelStream().map(handleFile).forEach(c -> {
         try {
             final HttpResponse<String> response = c.get();
             System.out.println(response.statusCode());
         } catch (Exception e) {
             e.printStackTrace(); …
Run Code Online (Sandbox Code Playgroud)

java file-upload http2 java-http-client

0
推荐指数
1
解决办法
1726
查看次数

闪烁的 HttpClient 有时会抛出 IOException

java.net.http.HttpClient.newHttpClient()在 Java 19 (Temurin) 下使用,并sendAsync(...)在同一实例上执行来自不同步骤的请求。我认为这是可以的,正如 javadoc 所说:

一旦构建,HttpClient 就是不可变的......

但是,某些请求会失败并显示以下信息:

java.io.IOException: HTTP/1.1 header parser received no bytes
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这取决于我的请求的速度:

  • 每 5 秒请求一次:30% 失败
  • 每 3 秒请求一次:0% 失败

我为它写了一个测试:

private final HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://..."))
    .setHeader("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofByteArray("[]".getBytes()))
    .build();

@ParameterizedTest
@ValueSource(ints = {3, 5})
void httpClientTest(int intervalSeconds) throws Exception {
    HttpClient httpClient = HttpClient.newHttpClient();

    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
    Thread.sleep(Duration.ofSeconds(intervalSeconds));
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()).get();
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试过以下操作:

  • curl在命令行上执行相同的操作。无论我尝试什么时间间隔,都没有请求失败。所以应该不是服务器的问题。
  • 并行运行多次测试。5 秒间隔仍然失败(然后并行多次)。所以应该不是服务器的问题。
  • HttpClient.newHttpClient() …

java-http-client java-19

0
推荐指数
1
解决办法
1356
查看次数

将Java 9 HttpClient代码升级到Java 11:BodyProcessor和asString()

我有一个代码库(显然)可以在下运行,Java 9但不能在下编译Java 11。它使用jdk.incubator.httpclientAPI并根据答案更改模块信息在大多数情况下都有效,但不仅仅是软件包已更改。

我仍然无法解决的代码如下:

private static JSONObject sendRequest(JSONObject json) throws Exception {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest httpRequest = HttpRequest.newBuilder(new URI(BASE_URL))
            .header("Accept", "application/json")
            .header("Content-Type", "application/json")
            .timeout(TIMEOUT_DURATION)
            .POST(HttpRequest.BodyProcessor.fromString(json.toString()))
            .build();

    HttpResponse<String> httpResponse = client.send(httpRequest, HttpResponse.BodyHandler.asString());
    String jsonResponse = httpResponse.body();

    return new JSONObject(jsonResponse);
}
Run Code Online (Sandbox Code Playgroud)

编译错误为:

Error:(205, 94) java: cannot find symbol
  symbol:   method asString()
  location: interface java.net.http.HttpResponse.BodyHandler
Error:(202, 34) java: cannot find symbol
  symbol:   variable BodyProcessor
  location: class java.net.http.HttpRequest
Run Code Online (Sandbox Code Playgroud)

如何将代码转换为等效Java 11版本?

java json java-9 java-http-client java-11

-4
推荐指数
1
解决办法
367
查看次数