Java 11이 가져온 새로운 HTTP 클라이언트를 사용해 봅시다.



Java 11은 내장 HTTP 클라이언트를 가져왔습니다. 결과적으로 HTTP 요청을 호출하기 위해 더 이상 타사 라이브러리가 필요하지 않습니다.

임의의 농담을 가져오기 위해 척 노리스 API를 호출해 봅시다.

package com.bazlur;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class Day011 {
  public static final String CHUCK_NORRIS_RANDOM_JOKES_API = "https://api.chucknorris.io/jokes/random";

  public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
    var client = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(20))
            .build();

    var request = HttpRequest.newBuilder()
            .uri(new URI(CHUCK_NORRIS_RANDOM_JOKES_API))
            .header("Accept", "application/json")
            .GET()
            .build();

    var response = client.send(request, HttpResponse.BodyHandlers.ofString());
    var body = response.body();
    System.out.println("body = " + body);
  }
}



비동기적으로 가져올 수도 있습니다. 메서드send()sendAsync()로 변경하기만 하면 됩니다.

 var completableFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body);


CompletableFuture 를 반환합니다.

JSON 본문을 개체로 직렬화하기 위해 직렬 변환기를 연결하는 데 더 나아갈 수 있습니다. 그러나 Jackson은 내가 모든 프로젝트에서 사용하는 가장 좋아하는 JSON 라이브러리입니다.

dependency을 추가해 보겠습니다.

implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.3'



람다 체인을 사용할 수 있도록 sendAsync() 메서드를 사용하겠습니다. ObjectMapper 메서드의 readValue()는 내 람다 식에 넣고 싶지 않은 확인된 예외를 throw합니다. 그것은 코드를 추악하게 만듭니다. 따라서 내 필요를 수용하기 위해 ObjectMapper의 동작을 약간 확장할 것입니다.

  static class UncheckedObjectMapper extends ObjectMapper {
    Joke readValue(String content) {
      try {
        return this.readValue(content, new TypeReference<>() {
        });
      } catch (JsonProcessingException e) {
        throw new CompletionException(e);
      }
    }
  }



나는 당신이 그것을 유지하려는 의지가 없다면 생산 코드에서 이런 종류의 변경을 권장하지 않을 것입니다. 조심해!

일반적으로 API에서 이 JSON 응답을 얻습니다.

{
  "categories": [],
  "created_at": "2020-01-05 13:42:28.420821",
  "icon_url": "https://assets.chucknorris.host/img/avatar/chuck-norris.png",
  "id": "Kqck_igkQNCw6Y0ADR2iyA",
  "updated_at": "2020-01-05 13:42:28.420821",
  "url": "https://api.chucknorris.io/jokes/Kqck_igkQNCw6Y0ADR2iyA",
  "value": "The Terminator wears a Chuck Norris tee shirt. ."
}



이를 위해 POJO를 생성해 보겠습니다. 이를 위해 record를 사용하겠습니다.


  @JsonIgnoreProperties(ignoreUnknown = true)
  record Joke(
          @JsonProperty("created_at")
          String createdAt,
          @JsonProperty("icon_url")
          String iconUrl,
          @JsonProperty("id")
          String id,
          @JsonProperty("updated_at")
          String updatedAt,
          @JsonProperty("url")
          String url,
          @JsonProperty("value")
          String value
  ) { }



모든 것을 하나로 합치자.

package com.bazlur;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;

public class Day011_1 {

  public static final String CHUCKNORRIS_RANDOM_JOKES_API = "https://api.chucknorris.io/jokes/random";

  public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException, ExecutionException {

    var objectMapper = new UncheckedObjectMapper();
    objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);

    var httpClient = HttpClient.newHttpClient();
    var request = HttpRequest.newBuilder()
            .uri(new URI(CHUCKNORRIS_RANDOM_JOKES_API))
            .header("Accept", "application/json")
            .GET()
            .build();

    var joke = httpClient.sendAsync(request, BodyHandlers.ofString())
            .thenApply(HttpResponse::body)
            .thenApply(objectMapper::readValue)
            .get();
    System.out.println("joke = " + joke.value());
  }

  @JsonIgnoreProperties(ignoreUnknown = true)
  record Joke(
          @JsonProperty("created_at")
          String createdAt,
          @JsonProperty("icon_url")
          String iconUrl,
          @JsonProperty("id")
          String id,
          @JsonProperty("updated_at")
          String updatedAt,
          @JsonProperty("url")
          String url,
          @JsonProperty("value")
          String value
  ) { }

  static class UncheckedObjectMapper extends ObjectMapper {
    Joke readValue(String content) {
      try {
        return this.readValue(content, new TypeReference<>() {
        });
      } catch (JsonProcessingException e) {
        throw new CompletionException(e);
      }
    }
  }
}



복사/붙여넣기: https://github.com/rokon12/100DaysOfJava/blob/main/src/main/java/com/bazlur/Day011.java

좋은 웹페이지 즐겨찾기