实验性地在Java 9中引入的HttpClient现在在Java 11中是稳定的,但毫不奇怪,很少有项目似乎实际使用它.文档几乎不存在.
在进行HTTP调用时,最常见的一个问题是记录请求/响应.你如何使用HttpClient,而不是在每次通话中手动记录它?是否有像所有其他HTTP客户端提供的拦截器机制?
基本上如标题所说。Apache HttpClient 和 Spring RestTemplate 允许定义自定义拦截器,这些拦截器环绕请求/响应并允许额外(全局)修改请求参数、日志记录等......
我在标准 Java 实现中没有看到这样的功能java.net.http.HttpClient(从 Java 11 开始)。我是否遗漏了某些东西,或者没有办法在单个上拦截所有请求/响应HttpClient?
有没有办法java.net.http.HttpClient立即释放它所持有的资源?
在内部,它包含一个选择器,一个连接池和一个Executor(当使用默认值时).但它没有实现Closeable/ AutoCloseable.
我编写了以下HttpClient代码,但它没有导致将Authorization标头发送到服务器:
public static void main(String[] args) {
var client = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password".toCharArray());
}
})
.version(HttpClient.Version.HTTP_1_1)
.build();
var request = HttpRequest.newBuilder()
.uri("https://service-that-needs-auth.example/")
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
}
Run Code Online (Sandbox Code Playgroud)
我从我正在调用的服务中收到HTTP 401错误.就我而言,它是Atlassian Jira Cloud API.
我已经确认我的getPasswordAuthentication()方法没有被HttpClient调用.
为什么它不起作用,我该怎么做呢?
Java 11java.net.http.HttpClient似乎不检查 HTTP 状态代码,重定向除外(如果启用)。wiki和 Java API 文档中找到的所有示例始终假设 HTTP 请求是成功的,即它们似乎从不检查响应的状态代码。
这很可能永远不是所需的行为,因为来自 HTTP 500(服务器错误)响应的错误页面可能具有不同的格式或没有格式,因此应用程序无法处理。
应该在哪里检查 HTTP 状态代码?
的文档HttpResponse.BodyHandler包含以下示例片段:
BodyHandler<Path> bodyHandler = (rspInfo) -> rspInfo.statusCode() == 200
? BodySubscribers.ofFile(Paths.get("/tmp/f"))
: BodySubscribers.replacing(Paths.get("/NULL"));
Run Code Online (Sandbox Code Playgroud)
但是,您必须检查两次状态代码,一次在BodyHandler上面显示的情况下,一次在处理响应时(因为尝试从中读取正文"/NULL"会失败)。
对我来说,仅执行 HTTP 状态代码检查似乎是最合理的BodyHandler,例如:
BodyHandler<Path> bodyHandler = (rspInfo) -> {
if (rspInfo.statusCode() == 200) {
return BodySubscribers.ofFile(Paths.get("/tmp/f"));
} else {
throw new RuntimeException("Request failed");
}
};
Run Code Online (Sandbox Code Playgroud)
但是,BodyHandler文档没有提及是否允许抛出异常,或者HttpClient在这种情况下会如何表现。
让我感到惊讶的是,JDK 似乎没有提供开箱即用的处理不成功 HTTP 响应的功能,还是我忽略了某些东西?
我正在尝试使用Java 9 maven项目中的孵化器中的HttpClient.我没有得到任何编译问题.该项目成功建立.但是当我尝试运行Main类时,它给了我以下异常:
Exception in thread "main" java.lang.NoClassDefFoundError: jdk/incubator/http/HttpClient
at java9.http_client.Main.main(Main.java:18)
Caused by: java.lang.ClassNotFoundException: jdk.incubator.http.HttpClient
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)....
Run Code Online (Sandbox Code Playgroud)
我的代码只是一个模块信息文件和一个只调用google.com并试图读取响应的Main类:
module-info.java
module java9.http_client {
requires jdk.incubator.httpclient;
}
Run Code Online (Sandbox Code Playgroud)
Main.java
public final class Main {
public static void main(String[] args) {
try {
HttpClient client = HttpClient.newHttpClient();
URI httpURI = new URI("http://www.google.com/");
HttpRequest request = HttpRequest.newBuilder(httpURI).GET().build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());
String responseBody = response.body();
int responseStatusCode = response.statusCode();
System.out.println(responseBody + "\n" + responseStatusCode);
} catch (URISyntaxException | IOException | …Run Code Online (Sandbox Code Playgroud) 我正在尝试测试使用新 Java 11 的代码java.net.http.HttpClient。
在我的生产代码中,我有这样的事情:
HttpClient httpClient = ... (gets injected)
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:1234"))
.POST(HttpRequest.BodyPublishers.ofByteArray("example".getBytes()))
.build();
return httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());
Run Code Online (Sandbox Code Playgroud)
在我的测试中,我模拟HttpClient了java.net.http.HttpRequest. 如何获取/测试其请求正文(= my "example")?我可以打电话request.bodyPublisher()来获取HttpRequest.BodyPublisher,但后来我被卡住了。
jdk.internal.net.http.RequestPublishers.ByteArrayPublisher(它实际上是),但它不会编译,因为模块没有导出相应的包。HttpRequest.BodyPublisher-interface ( .contentLength(), .subscribe(subscriber)) 中的可用方法,但我想它们是不可能的。BodyPublisher并使用 比较它们.equals(),但没有真正的实现,所以比较总是错误的。我正在尝试在简单的 Java 应用程序(使用java.net.http.WebSocket类)和google-chrome使用远程运行之间创建通信google-chrome --remote-debugging-port=9222 --user-data-dir=.
发送和接收小消息按预期工作,但在 16kb 大消息的情况下会出现问题。
这是java源代码的一部分:
var uri = new URI("ws://127.0.0.1:9222/devtools/page/C0D7B4DBC53FB39F7A4BE51DA79E96BB");
/// create websocket client
WebSocket ws = HttpClient
.newHttpClient()
.newWebSocketBuilder()
.connectTimeout(Duration.ofSeconds(30))
.buildAsync(uri, simpleListener)
.join();
// session Id attached to chrome tab
String sessionId = "...";
// send message
String message = "{\"id\":1,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"document.body.style.backgroundColor = 'blue';\",\"returnByValue\":true,\"awaitPromise\":true,\"userGesture\":true},\"sessionId\":\"" + sessionId + "\"}";
// this works
ws.send(message, true);
// generate big string contains over 18k chars for testing purpose
String bigMessage = "{\"id\":2,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"[" + ("1,".repeat(9000)) + …Run Code Online (Sandbox Code Playgroud) java websocket google-chrome-devtools java-http-client chrome-devtools-protocol
我看到 JDK9 中支持预告片(该HttpResponse.trailers\xe2\x80\x8b()方法),但在 JDK 10 上不再支持(该HttpResponse.trailers\xe2\x80\x8b()方法不存在)。
我目前正在使用 JDK11,当我尝试我的请求时:
\nHttpRequest request = HttpRequest.newBuilder()\n .uri(uri)\n .GET()\n .build();\n\n\nHttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());\nRun Code Online (Sandbox Code Playgroud)\n我面对一个java.util.concurrent.ExecutionException: java.io.IOException: no statuscode in response. 仅当我请求带有预告片标题的页面时,它才会失败。\n欢迎任何帮助。谢谢
当我需要以流方式处理响应时,我应该如何处理使用 Java 11 中包含的 HTTP 客户端挂起发送 HTTP 响应正文的服务器?
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(2))
.build();
HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("http://example.com"))
.timeout(Duration.ofSeconds(5))
.build();
HttpResponse<Stream<String>> httpResponse = httpClient
.send(httpRequest, HttpResponse.BodyHandlers.ofLines());
Stream<String> responseLineStream = httpResponse.body();
responseLineStream.count();
Run Code Online (Sandbox Code Playgroud)
在上面的代码中:
BodyHandler,当收到状态行和报头时,就认为收到了响应。这意味着当代码执行时,在 7 秒内要么抛出异常,要么到达最后一行。但是,最后一行不受任何超时的限制。如果服务器停止发送响应正文,最后一行将永远阻塞。
在这种情况下,如何防止最后一行挂起?
java ×10
java-http-client ×10
java-11 ×6
http ×3
java-9 ×2
interceptor ×1
java-module ×1
logging ×1
websocket ×1