CodeGym/Java 课程/模块 3/使用 HttpClient 发出请求

使用 HttpClient 发出请求

可用

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 协议传输到半个世界 :) :) :)

出色地。世界并不完美。

您可以在以下链接中阅读有关此主题的更多信息:

HTTP认证

了解 HTTP 身份验证

评论
  • 受欢迎
你必须先登录才能发表评论
此页面还没有任何评论