4.1 send()方法,BodyHandlers
您已经完成了如何形成http 请求的学习,因此您可以继续进行最重要的事情 - 发送此请求。在最简单的情况下,这很容易做到:
HttpRequest request = HttpRequest.newBuilder(new URI("https://codegym.cc")).build();
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode() );
System.out.println(response.body() );
这些是什么BodyHandlers
?你怎么认为?您发送了一个请求,这意味着您应该收到一个答复 - http response
。这个响应可以有response body
:一个字符串、一个文件、一个字节数组、一个 InputStream。
是的,是的,没错。就像在形成请求时,您需要指定response body
响应的类型。一共可以有8块:
BodyHandlers.ofByteArray
BodyHandlers.ofString
BodyHandlers.ofFile
BodyHandlers.discarding
BodyHandlers.replacing
BodyHandlers.ofLines
BodyHandlers.fromLineSubscriber
根据BodyHandlers
您传递给方法的类型send()
,它会返回这样的结果类型。例子:
// response body is ignored
HttpResponse<Void> response = client.send(request, BodyHandlers.discarding());
// response body is a string
HttpResponse<String>response = client.send(request, BodyHandlers.ofString());
// response body is a file
HttpResponse<Path> response = client.send(request, BodyHandlers.ofFile(Paths.get("readme.txt")));
// response body is an InputStream
HttpResponse<InputStream> response = client.send(request, BodyHandlers.ofInputStream());
如果应将文件作为响应发送给您,则BodyHandlers.ofFile()
需要将本地文件的名称传递给该方法,该文件将由 HttpClient 对象保存在该方法中。
4.2 followRedirects()方法
301
此外,在发送请求时,您可以指定如果服务器发送或302
(临时或永久重定向)响应HttpClient 应该做什么。假设服务器发送了一个代码302
,您需要:跟踪这种情况,从响应中获取新的 URL,并将请求发送到新地址。
我不太愿意这样做,特别是考虑到这种情况很常见并且长期以来在所有 http 客户端中都是自动化的。同样在此 HttpClient 中,您只需要指定发送请求时选择的重定向模式。
HttpResponse response = HttpClient.newBuilder()
.followRedirects( HttpClient.Redirect.ALWAYS )
.build()
.send(request, BodyHandlers.ofString());
重定向只有 3 个选项:
- ALWAYS——一直;
- NEVER——从不;
- 正常- 总是,除了 HTTPS -> HTTP。
如您所见,这里的选项不多,但有定制能力总比没有好。
4.4 proxy() 方法
还有一些更有用但不常用的选项。在你需要它们之前你不需要它们:)
第一个是代理。在日常生活中,你不会经常遇到它们,但很多大公司内部都有复杂的互联网流量安全系统,因此代理设置也各不相同。
好吧,当然,您的软件将在这样一家公司的内部某个地方运行,总有一天会遇到需要使用代理的事实。因此,这里也有这样的选择是件好事。
设置代理非常简单 - 例如:
HttpResponse<String> response = HttpClient.newBuilder()
.proxy( ProxySelector.getDefault())
.build()
.send(request, BodyHandlers.ofString());
此处已选择默认代理,但您可能需要设置自己的代理:
HttpResponse response = HttpClient.newBuilder()
.proxy(ProxySelector.of(new InetSocketAddress("proxy.microsoft.com", 80)))
.build()
.send(request, BodyHandlers.ofString());
我们不会考虑如何使用代理,因为这不包括在本课程的范围内。
4.5 验证器()
还有一点很重要。HTTP 协议支持身份验证。就在协议级别。
现在这种方法几乎不用了,但大约 20 年前它很常见。Http 请求如下所示:
http://username@example.com/
或者甚至像这样:
http://username:password@example.com/
这不是邮件。这正是链接。是的,你不这么认为。可以在 http 请求中直接指定登录名甚至密码。是的,即使现在你也可以。这就是为什么我写道,现在通常没有人这样做。但是有这样的可能。
Authenticator auth = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"username",
"password".toCharArray());
}
};
HttpResponse<String> response = HttpClient.newBuilder()
.authenticator(auth).build()
.send(request, BodyHandlers.ofString());
这很有趣!你知道为什么而不是“password"
在它说的代码中吗"password".toCharArray()
?
因为构造函数的第二个参数PasswordAuthentication
不是String
,而是CharArray
。
为什么第二个参数不是String
,嗯CharArray
?
因为为了安全起见,所有的密码都不允许作为一个完整的字符串存储,即使是在你自己的应用程序中也是如此。也就是说,您的应用程序在其内存中不应将密码存储为字符串。这样一来,如果有人弄湿了记忆,就无法从中提取密码...
但与此同时,密码可以通过不安全的 HTTP 协议传输到半个世界 :) :) :)
出色地。世界并不完美。
您可以在以下链接中阅读有关此主题的更多信息:
GO TO FULL VERSION