Java >> Java tutorial >  >> Tag >> HTTP

Sender med Java HttpClient

1. Oversigt

Java HttpClient API blev introduceret med Java 11. API implementerer klientsiden af ​​de seneste HTTP-standarder . Den understøtter HTTP/1.1 og HTTP/2, både synkrone og asynkrone programmeringsmodeller.

Vi kan bruge det til at sende HTTP-anmodninger og hente deres svar. Før Java 11 var vi nødt til at stole på en rudimentær URLCconnection implementering eller tredjepartsbiblioteker såsom Apache HttpClient .

I denne vejledning ser vi på afsendelse af POST-anmodninger ved hjælp af Java HttpClient . Vi viser, hvordan du sender både synkrone og asynkrone POST-anmodninger, såvel som samtidige POST-anmodninger. Derudover vil vi tjekke, hvordan man tilføjer godkendelsesparametre og JSON-kroppe til POST-anmodninger.

Til sidst vil vi se, hvordan du uploader filer og indsender formulardata. Derfor vil vi dække de fleste af de almindelige brugssager.

2. Forberedelse af en POST-anmodning

Før vi kan sende en HTTP-anmodning, skal vi først oprette en forekomst af en HttpClient .

HttpClient instanser kan konfigureres og oprettes fra dens builder ved hjælp af newBuilder metode. Ellers, hvis der ikke kræves nogen konfiguration, kan vi gøre brug af newHttpClient hjælpemetode til at oprette en standardklient:

HttpClient client = HttpClient.newHttpClient();

HttpClient vil bruge HTTP/2 som standard. Den vil også automatisk nedgradere til HTTP/1.1, hvis serveren ikke understøtter HTTP/2.

Nu er vi klar til at oprette en forekomst af HttpRequest fra sin bygherre. Vi vil gøre brug af klientinstansen til at sende denne anmodning senere. Minimumsparametrene for en POST-anmodning er serverens URL, anmodningsmetode og brødtekst:

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create(serviceUrl))
  .POST(HttpRequest.BodyPublishers.noBody())
  .build();

En anmodningstekst skal leveres via BodyPublisher klasse. Det er en reaktiv-stream-udgiver, der udgiver streams af anmodningsorgan efter behov. I vores eksempel brugte vi en kropsudgiver, som ikke sender nogen anmodningstekst.

3. Sender en POST-anmodning

Nu hvor vi har forberedt en POST-anmodning, lad os se på de forskellige muligheder for at sende den.

3.1. Synkront

Vi kan sende den forberedte anmodning ved at bruge denne standard send metode. Denne metode vil blokere vores kode, indtil svaret er modtaget :

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString())

BodyHandlers utility implementerer forskellige nyttige handlere, såsom håndtering af svarlegemet som en streng eller streaming af svarteksten til en fil. Når svaret er modtaget, vises HttpResponse objekt vil indeholde svarstatus, overskrifter og brødtekst:

assertThat(response.statusCode())
  .isEqualTo(200);
assertThat(response.body())
  .isEqualTo("{\"message\":\"ok\"}");

3.2. Asynkront

Vi kunne sende den samme anmodning fra det forrige eksempel asynkront ved hjælp af sendAsync metode. I stedet for at blokere vores kode, vil denne metode straks returnere en CompletableFuture forekomst :

CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());

CompletableFuture afsluttes med HttpResponse  når den bliver tilgængelig:

HttpResponse<String> response = futureResponse.get();
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");

3.3. Samtidig

Vi kan kombinere Streams med CompletableFutures for at udsende flere anmodninger samtidigt og afvente deres svar :

List<CompletableFuture<HttpResponse<String>>> completableFutures = serviceUrls.stream()
  .map(URI::create)
  .map(HttpRequest::newBuilder)
  .map(builder -> builder.POST(HttpRequest.BodyPublishers.noBody()))
  .map(HttpRequest.Builder::build)
  .map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
  .collect(Collectors.toList());

Lad os nu vente på, at alle anmodninger er fuldstændige, så vi kan behandle deres svar på én gang:

CompletableFuture<List<HttpResponse<String>>> combinedFutures = CompletableFuture
  .allOf(completableFutures.toArray(new CompletableFuture[0]))
  .thenApply(future ->
    completableFutures.stream()
      .map(CompletableFuture::join)
      .collect(Collectors.toList()));

Da vi har kombineret alle svarene ved hjælp af allOf og deltag metoder, får vi en ny CompletableFuture der holder vores svar:

List<HttpResponse<String>> responses = combinedFutures.get();
responses.forEach((response) -> {
  assertThat(response.statusCode()).isEqualTo(200);
  assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
});

4. Tilføjelse af godkendelsesparametre

Vi kan indstille en autentificering på klientniveau til HTTP-godkendelse på alle anmodninger :

HttpClient client = HttpClient.newBuilder()
  .authenticator(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
      return new PasswordAuthentication(
        "baeldung",
        "123456".toCharArray());
      }
  })
  .build();

Men HttpClient sender ikke grundlæggende legitimationsoplysninger, før de udfordres med en WWW-godkendt header fra serveren.

For at omgå dette kan vi altid oprette og sende den grundlæggende autorisationsheader manuelt:

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create(serviceUrl))
  .POST(HttpRequest.BodyPublishers.noBody())
  .header("Authorization", "Basic " + 
    Base64.getEncoder().encodeToString(("baeldung:123456").getBytes()))
  .build();

5. Tilføjelse af en krop

I eksemplerne indtil videre har vi ikke tilføjet nogen tekster til vores POST-anmodninger. POST-metoden bruges dog almindeligvis til at sende data til serveren via anmodningsteksten .

5.1. JSON Body

BodyPublishers hjælpeprogrammet implementerer forskellige nyttige udgivere, såsom udgivelse af anmodningsteksten fra en streng eller en fil. Vi kan offentliggøre JSON-data som streng , konverteret ved hjælp af UTF-8-tegnsættet:

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create(serviceUrl))
  .POST(HttpRequest.BodyPublishers.ofString("{\"action\":\"hello\"}"))
  .build();

5.2. Uploader filer

Lad os oprette en midlertidig fil, som vi kan bruge til at uploade via HttpClient :

Path file = tempDir.resolve("temp.txt");
List<String> lines = Arrays.asList("1", "2", "3");
Files.write(file, lines);

HttpClient giver en separat metode, BodyPublishers.ofFile, for at tilføje en fil til POST-teksten . Vi kan blot tilføje vores midlertidige fil som en metodeparameter, og API'en tager sig af resten:

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create(serviceUrl))
  .POST(HttpRequest.BodyPublishers.ofFile(file))
  .build();

5.3. Indsendelse af formularer

I modsætning til filer, HttpClient giver ikke en separat metode til bogføring af formulardata. Derfor bliver vi igen nødt til at gøre brug af BodyPublishers.ofString metode :

Map<String, String> formData = new HashMap<>();
formData.put("username", "baeldung");
formData.put("message", "hello");

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create(serviceUrl))
  .POST(HttpRequest.BodyPublishers.ofString(getFormDataAsString(formData)))
  .build();

Vi bliver dog nødt til at konvertere formulardataene fra et Kort til en streng ved hjælp af en tilpasset implementering:

private static String getFormDataAsString(Map<String, String> formData) {
    StringBuilder formBodyBuilder = new StringBuilder();
    for (Map.Entry<String, String> singleEntry : formData.entrySet()) {
        if (formBodyBuilder.length() > 0) {
            formBodyBuilder.append("&");
        }
        formBodyBuilder.append(URLEncoder.encode(singleEntry.getKey(), StandardCharsets.UTF_8));
        formBodyBuilder.append("=");
        formBodyBuilder.append(URLEncoder.encode(singleEntry.getValue(), StandardCharsets.UTF_8));
    }
    return formBodyBuilder.toString();
}

6. Konklusion

I denne artikel, vi undersøgte afsendelse af POST-anmodninger ved hjælp af Java HttpClient API introduceret i Java 11 .

Vi lærte, hvordan man opretter en HttpClient instans og forberede en POST-anmodning. Vi så, hvordan man sender forberedte anmodninger synkront, asynkront og samtidigt. Dernæst så vi også, hvordan man tilføjer grundlæggende godkendelsesparametre.

Til sidst så vi på at tilføje et brød til en POST-anmodning. Vi dækkede JSON-nyttelast, upload af filer og indsendelse af formulardata.

Som altid er den komplette kildekode tilgængelig på GitHub.


Java tag