1. 소개
이 예제에서는 Java 9의 새로운 인큐베이팅 HttpClient 를 살펴보겠습니다 .
아주 최근까지 Java는 HttpURLConnection API 만 제공했습니다. 이 API는 수준이 낮고 기능이 풍부 하고 사용자 친화적인 것으로 알려져 있지 않습니다 .
따라서 Apache HttpClient , Jetty 및 Spring의 RestTemplate 과 같이 널리 사용되는 일부 타사 라이브러리가 일반적으로 사용되었습니다 .
2. 초기 설정
HTTP 클라이언트 모듈은 JDK 9 의 인큐베이터 모듈로 번들되며 여전히 HTTP/1.1을 용이하게 하는 이전 버전과의 호환성으로 HTTP/2 를 지원합니다 .
이를 사용하려면 애플리케이션을 실행하는 데 필요한 모듈을 나타내는 module-info.java 파일을 사용하여 모듈을 정의해야 합니다.
module com.baeldung.java9.httpclient {
requires jdk.incubator.httpclient;
}
3. HTTP 클라이언트 API 개요
HttpURLConnection 과 달리 HTTP 클라이언트는 동기 및 비동기 요청 메커니즘을 제공합니다.
API는 3가지 핵심 클래스로 구성됩니다.
- HttpRequest – HttpClient 를 통해 보낼 요청을 나타냅니다.
- HttpClient – 여러 요청에 공통적인 구성 정보의 컨테이너 역할을 합니다.
- HttpResponse – HttpRequest 호출 의 결과를 나타냅니다.
다음 섹션에서 각각에 대해 더 자세히 살펴보겠습니다. 먼저 요청에 중점을 두겠습니다.
4. HttpRequest
HttpRequest 는 이름에서 알 수 있듯이 보내려는 요청을 나타내는 객체입니다. HttpRequest.Builder를 사용하여 새 인스턴스를 만들 수 있습니다 .
HttpRequest.newBuilder() 를 호출하여 얻을 수 있습니다 . Builder 클래스는 요청을 구성하는 데 사용할 수 있는 많은 메서드를 제공합니다.
우리는 가장 중요한 것들을 다룰 것입니다.
4.1. 설정 URI
요청을 생성할 때 가장 먼저 해야 할 일은 URL을 제공하는 것입니다.
URI 매개변수 와 함께 Builder 용 생성자를 사용 하거나 Builder 인스턴스 에서 uri(URI) 메소드를 호출하는 두 가지 방법으로 이를 수행할 수 있습니다 .
HttpRequest.newBuilder(new URI("https://postman-echo.com/get"))
HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
기본 요청을 생성하기 위해 구성해야 하는 마지막 사항은 HTTP 메서드입니다.
4.2. HTTP 메서드 지정
Builder 에서 메소드 중 하나를 호출하여 요청이 사용할 HTTP 메소드를 정의할 수 있습니다 .
- 가져 오기()
- POST(BodyProcessor 본체)
- PUT(BodyProcessor 본체)
- DELETE(BodyProcessor 본체)
BodyProcessor 에 대해서는 나중에 자세히 다루 겠습니다 . 이제 매우 간단한 GET 요청 예제를 만들어 보겠습니다 .
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.GET()
.build();
이 요청에는 HttpClient에 필요한 모든 매개변수가 있습니다. 그러나 때로는 요청에 추가 매개변수를 추가해야 합니다. 다음은 몇 가지 중요한 사항입니다.
- HTTP 프로토콜의 버전
- 헤더
- 타임아웃
4.3. HTTP 프로토콜 버전 설정
API는 HTTP/2 프로토콜을 완전히 활용하고 기본적으로 이를 사용하지만 사용하려는 프로토콜 버전을 정의할 수 있습니다.
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.version(HttpClient.Version.HTTP_2)
.GET()
.build();
여기서 언급해야 할 중요한 점은 예를 들어 HTTP/2가 지원되지 않는 경우 클라이언트가 HTTP/1.1로 대체한다는 것입니다.
4.4. 헤더 설정
요청에 추가 헤더를 추가하려는 경우 제공된 빌더 메서드를 사용할 수 있습니다.
다음 두 가지 방법 중 하나로 이를 수행할 수 있습니다.
- 모든 헤더를 키-값 쌍으로 headers() 메서드에 전달하거나
- 단일 키-값 헤더에 대해 header() 메서드 사용 :
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.headers("key1", "value1", "key2", "value2")
.GET()
.build();
HttpRequest request2 = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.header("key1", "value1")
.header("key2", "value2")
.GET()
.build();
요청을 사용자 정의하는 데 사용할 수 있는 마지막 유용한 방법은 timeout() 입니다.
4.5. 시간 초과 설정
이제 응답을 기다리는 시간을 정의해 보겠습니다.
설정된 시간이 만료되면 HttpTimeoutException 이 발생합니다. 기본 시간 초과는 무한대로 설정됩니다.
빌더 인스턴스에서 timeout() 메서드를 호출 하여 Duration 객체로 타임아웃을 설정할 수 있습니다 .
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.timeout(Duration.of(10, SECONDS))
.GET()
.build();
5. 요청 본문 설정
요청 빌더 메소드인 POST(BodyProcessor body) , PUT(BodyProcessor body) 및 DELETE(BodyProcessor body) 를 사용하여 요청에 본문을 추가할 수 있습니다 .
새 API는 요청 본문 전달을 단순화하는 즉시 사용 가능한 여러 BodyProcessor 구현을 제공합니다 .
- StringProcessor ( HttpRequest.BodyProcessor.fromString 으로 생성 된 String 에서 본문 읽기 )
- InputStreamProcessor ( HttpRequest.BodyProcessor.fromInputStream 으로 생성 된 InputStream 에서 본문 읽기 )
- ByteArrayProcessor ( HttpRequest.BodyProcessor.fromByteArray 로 만든 바이트 배열에서 본문 읽기 )
- FileProcessor ( HttpRequest.BodyProcessor.fromFile 로 생성된 지정된 경로의 파일에서 본문을 읽음 )
본문이 필요하지 않은 경우 HttpRequest.noBody() 를 전달할 수 있습니다 .
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/post"))
.POST(HttpRequest.noBody())
.build();
5.1. StringBodyProcessor
BodyProcessor 구현 으로 요청 본문을 설정하는 것은 매우 간단하고 직관적입니다.
예를 들어 간단한 String 을 본문으로 전달하려는 경우 StringBodyProcessor 를 사용할 수 있습니다 .
이미 언급했듯이 이 객체는 fromString() 팩토리 메서드로 생성할 수 있습니다 . 그것은 단지 String 객체를 인수로 취하고 그것 으로부터 본문을 생성합니다:
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/post"))
.headers("Content-Type", "text/plain;charset=UTF-8")
.POST(HttpRequest.BodyProcessor.fromString("Sample request body"))
.build();
5.2. InputStreamBodyProcessor
그렇게 하려면 InputStream 이 공급자 로 전달되어야 하므로(생성을 지연시키기 위해) 위에서 설명한 StringBodyProcessor와 약간 다릅니다 .
그러나 이것은 또한 매우 간단합니다.
byte[] sampleData = "Sample request body".getBytes();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/post"))
.headers("Content-Type", "text/plain;charset=UTF-8")
.POST(HttpRequest.BodyProcessor
.fromInputStream(() -> new ByteArrayInputStream(sampleData)))
.build();
여기 에서 간단한 ByteArrayInputStream 을 사용한 방법에 주목 하십시오. 물론 모든 InputStream 구현이 될 수 있습니다 .
5.3. 바이트 배열 프로세서
ByteArrayProcessor 를 사용 하고 바이트 배열을 매개변수로 전달할 수도 있습니다 .
byte[] sampleData = "Sample request body".getBytes();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/post"))
.headers("Content-Type", "text/plain;charset=UTF-8")
.POST(HttpRequest.BodyProcessor.fromByteArray(sampleData))
.build();
5.4. 파일 프로세서
File로 작업하기 위해 제공된 FileProcessor를 사용할 수 있습니다 . 팩토리 메소드는 파일의 경로를 매개변수로 취하고 내용에서 본문을 작성합니다.
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/post"))
.headers("Content-Type", "text/plain;charset=UTF-8")
.POST(HttpRequest.BodyProcessor.fromFile(
Paths.get("src/test/resources/sample.txt")))
.build();
HttpRequest 를 생성하는 방법 과 추가 매개변수를 설정하는 방법을 다루었 습니다.
이제 요청을 보내고 응답을 받는 HttpClient 클래스를 자세히 살펴보겠습니다 .
6. Http클라이언트
모든 요청은 HttpClient.newBuilder() 메서드를 사용하거나 HttpClient.newHttpClient() 를 호출 하여 인스턴스화할 수 있는 HttpClient 를 사용하여 전송됩니다 .
요청/응답을 처리하는 데 사용할 수 있는 유용하고 자체 설명적인 방법을 많이 제공합니다.
여기에서 몇 가지를 살펴보겠습니다.
6.1. 프록시 설정
연결에 대한 프록시를 정의할 수 있습니다. Builder 인스턴스 에서 proxy() 메서드를 호출하기만 하면 됩니다 .
HttpResponse<String> response = HttpClient
.newBuilder()
.proxy(ProxySelector.getDefault())
.build()
.send(request, HttpResponse.BodyHandler.asString());
이 예에서는 기본 시스템 프록시를 사용했습니다.
6.2. 리디렉션 정책 설정
액세스하려는 페이지가 다른 주소로 이동하는 경우가 있습니다.
이 경우 일반적으로 새 URI에 대한 정보와 함께 HTTP 상태 코드 3xx를 받게 됩니다. 적절한 리디렉션 정책을 설정하면 HttpClient 가 자동으로 요청을 새 URI로 리디렉션할 수 있습니다.
Builder 의 followRedirects() 메서드를 사용하여 수행할 수 있습니다 .
HttpResponse<String> response = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.ALWAYS)
.build()
.send(request, HttpResponse.BodyHandler.asString());
모든 정책은 enum HttpClient.Redirect 에 정의 및 설명되어 있습니다.
6.3. 연결에 대한 인증자 설정
인증자는 연결에 대한 자격 증명 (HTTP 인증) 협상 객체입니다.
다양한 인증 체계(예: 기본 또는 다이제스트 인증)를 제공합니다. 대부분의 경우 인증 시 서버에 연결하려면 사용자 이름과 암호가 필요합니다.
다음 값의 보유자일 뿐인 PasswordAuthentication 클래스를 사용할 수 있습니다 .
HttpResponse<String> response = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"username",
"password".toCharArray());
}
}).build()
.send(request, HttpResponse.BodyHandler.asString());
위의 예에서 사용자 이름과 비밀번호 값을 일반 텍스트로 전달했습니다. 물론 프로덕션 시나리오에서는 달라야 합니다.
모든 요청에 동일한 사용자 이름과 암호를 사용해야 하는 것은 아닙니다. 인증 자 클래스는 다수 제공 하는 getXXX를 (예를 들어, getRequestingSite () ) 값을 제공해야한다 무엇을 찾을 수 있습니다 방법.
이제 새로운 HttpClient 의 가장 유용한 기능 중 하나인 서버에 대한 비동기식 호출을 살펴보겠습니다 .
6.4. 요청 보내기 – 동기화 대 비동기
새로운 HttpClient는 서버에 요청을 보내는 두 가지 가능성을 제공합니다.
- send(…) – 동기식 (응답이 올 때까지 차단)
- sendAsync(…) – 비동기식 (응답을 기다리지 않음, 비차단)
지금까지 send( ...) 메서드는 자연스럽게 응답을 기다립니다.
HttpResponse<String> response = HttpClient.newBuilder()
.build()
.send(request, HttpResponse.BodyHandler.asString());
이 호출은 HttpResponse 개체를 반환 하고 응답이 이미 있는 경우에만 응용 프로그램 흐름의 다음 명령이 실행될 것이라고 확신합니다.
그러나 특히 많은 양의 데이터를 처리할 때 많은 단점이 있습니다.
그래서, 지금, 우리가 사용할 수있는 가 SendAsync를 (. ..) 메소드 - 반환 CompletableFeature을 <HttpResponse에> - 비동기 요청을 처리 할 수 :
CompletableFuture<HttpResponse<String>> response = HttpClient.newBuilder()
.build()
.sendAsync(request, HttpResponse.BodyHandler.asString());
새로운 API는 여러 응답을 처리하고 요청 및 Response body을 스트리밍할 수도 있습니다.
List<URI> targets = Arrays.asList(
new URI("https://postman-echo.com/get?foo1=bar1"),
new URI("https://postman-echo.com/get?foo2=bar2"));
HttpClient client = HttpClient.newHttpClient();
List<CompletableFuture<String>> futures = targets.stream()
.map(target -> client
.sendAsync(
HttpRequest.newBuilder(target).GET().build(),
HttpResponse.BodyHandler.asString())
.thenApply(response -> response.body()))
.collect(Collectors.toList());
6.5. 비동기 호출을 위한 실행기 설정
비동기 호출에서 사용할 스레드를 제공 하는 Executor 를 정의할 수도 있습니다.
이 방법으로 예를 들어 요청 처리에 사용되는 스레드 수를 제한할 수 있습니다.
ExecutorService executorService = Executors.newFixedThreadPool(2);
CompletableFuture<HttpResponse<String>> response1 = HttpClient.newBuilder()
.executor(executorService)
.build()
.sendAsync(request, HttpResponse.BodyHandler.asString());
CompletableFuture<HttpResponse<String>> response2 = HttpClient.newBuilder()
.executor(executorService)
.build()
.sendAsync(request, HttpResponse.BodyHandler.asString());
기본적으로 HttpClient 는 실행자 java.util.concurrent.Executors.newCachedThreadPool()을 사용 합니다.
6.6. CookieManager 정의
새로운 API와 빌더를 사용하면 연결에 대한 CookieManager 를 설정하는 것이 간단 합니다. 빌더 메소드인 cookieManager(CookieManager cookieManager) 를 사용하여 클라이언트별 CookieManager 를 정의 할 수 있습니다 .
예를 들어 쿠키를 전혀 허용하지 않는 CookieManager 를 정의해 보겠습니다 .
HttpClient.newBuilder()
.cookieManager(new CookieManager(null, CookiePolicy.ACCEPT_NONE))
.build();
CookieManager가 쿠키 저장을 허용하는 경우 HttpClient 에서 CookieManager 를 확인하여 쿠키에 액세스할 수 있습니다 .
httpClient.cookieManager().get().getCookieStore()
이제 Http API의 마지막 클래스인 HttpResponse 에 집중해 보겠습니다 .
7. HttpResponse 객체
대한 HttpResponse 클래스는 서버의 응답을 나타냅니다. 여러 가지 유용한 방법을 제공하지만 가장 중요한 두 가지는 다음과 같습니다.
- statusCode() – 응답에 대한 상태 코드(유형 int )를 반환합니다 ( HttpURLConnection 클래스에는 가능한 값이 포함됨 ).
- body() – 응답에 대한 본문을 반환합니다(반환 유형은 send() 메서드에 전달된 응답 BodyHandler 매개변수 에 따라 다름 )
응답 객체에는 uri() , headers() , trailers() 및 version() 과 같은 다른 유용한 메서드가 있습니다.
7.1. 응답 객체의 URI
응답 객체의 uri() 메서드 는 응답 을 받은 URI 를 반환합니다 .
리디렉션이 발생할 수 있으므로 때때로 요청 개체의 URI 와 다를 수 있습니다.
assertThat(request.uri()
.toString(), equalTo("http://stackoverflow.com"));
assertThat(response.uri()
.toString(), equalTo("https://stackoverflow.com/"));
7.2. 응답의 헤더
응답 객체에서 headers() 메서드를 호출하여 응답에서 헤더를 얻을 수 있습니다 .
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());
HttpHeaders responseHeaders = response.headers();
그것은 반환 HttpHeaders의 반환 형식으로 개체를. 이것은 HTTP 헤더의 읽기 전용 보기를 나타내는 jdk.incubator.http 패키지에 정의된 새로운 유형 입니다.
헤더 값 검색을 단순화하는 몇 가지 유용한 방법이 있습니다.
7.3. 응답에서 예고편 가져오기
HTTP 응답에는 응답 내용 뒤에 포함되는 추가 헤더가 포함될 수 있습니다. 이러한 헤더를 트레일러 헤더라고 합니다.
HttpResponse 에서 trailers() 메서드를 호출하여 얻을 수 있습니다 .
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());
CompletableFuture<HttpHeaders> trailers = response.trailers();
참고 트레일러 () 메소드의 반환 CompletableFuture의 객체입니다.
7.4. 응답 버전
version() 메서드 는 서버와 통신하는 데 사용된 HTTP 프로토콜 버전을 정의합니다.
HTTP/2를 사용한다고 정의하더라도 서버는 HTTP/1.1을 통해 응답할 수 있음을 기억하십시오.
서버가 응답한 버전은 응답에 지정됩니다.
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.version(HttpClient.Version.HTTP_2)
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());
assertThat(response.version(), equalTo(HttpClient.Version.HTTP_1_1));
8. 자바 11 HTTP 클라이언트
Java 11의 주요 변경 사항은 HTTP/2 및 Web Socket을 구현하는 HTTP 클라이언트 API 의 표준화였습니다 . Java 초기부터 JDK에 존재했던 레거시 HttpUrlConnection 클래스 를 대체하는 것을 목표로 합니다 .
변경 사항은 JEP 321의 일부로 구현되었습니다.
8.1. JEP 321의 일부로 주요 변경 사항
- Java 9에서 배양된 HTTP API가 이제 공식적으로 Java SE API에 통합되었습니다. 새로운 HTTP API 는 java.net.HTTP.* 에서 찾을 수 있습니다 .
- 최신 버전의 HTTP 프로토콜은 클라이언트에서 요청을 보내고 서버에서 응답을 받는 전반적인 성능을 향상시키도록 설계되었습니다. 이는 스트림 다중화, 헤더 압축 및 푸시 약속과 같은 여러 변경 사항을 도입하여 달성됩니다.
- Java 11부터 API는 이제 완전히 비동기식입니다(이전 HTTP/1.1 구현은 차단됨). 비동기식 호출은 CompletableFuture를 사용하여 구현됩니다 . CompletableFuture 구현은 이전 단계가 완료되면 각 단계를 적용하므로 이 전체 흐름이 비동기식입니다.
- 새로운 HTTP 클라이언트 API는 타사 의존성을 추가할 필요 없이 HTTP/2와 같은 최신 웹 기능을 지원하여 HTTP 네트워크 작업을 수행하는 표준 방법을 제공합니다.
- 새 API는 HTTP 1.1/2 WebSocket에 대한 기본 지원을 제공합니다. 핵심 기능을 제공하는 핵심 클래스 및 인터페이스는 다음과 같습니다.
- HttpClient를 클래스, java.net.http.HttpClient
- HttpRequest에 클래스, java.net.http.HttpRequest
- HttpResponse에 <T> 인터페이스 java.net.http.HttpResponse
- 웹 소켓 인터페이스, java.net.http.WebSocket
8.2. Java 11 이전 HTTP 클라이언트의 문제
기존 HttpURLConnection API와 그 구현에는 다음과 같은 많은 문제가 있었습니다.
- URLConnection API는 더 이상 작동하지 않는 여러 프로토콜(FTP, gopher 등)로 설계되었습니다.
- API는 HTTP/1.1보다 이전 버전이며 너무 추상적입니다.
- 차단 모드에서만 작동합니다(즉, 요청/응답당 하나의 스레드).
- 유지하기가 매우 어렵습니다.
9. Java 11에서 Http 클라이언트의 변경 사항
9.1. 정적 팩토리 클래스 소개
새로운 정적 팩토리 클래스의 BodyPublishers , BodySubscribers, 및 BodyHandlers는 기존의 구현 등이 소개된다 BodyPublisher , BodySubscriber 및 BodyHandler을.
이들은 Response body을 문자열로 처리하거나 본문을 파일로 스트리밍하는 것과 같은 유용한 일반 작업을 수행하는 데 사용됩니다.
예를 들어 Pre Java 11에서는 다음과 같이 해야 했습니다.
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());
이제 다음과 같이 단순화할 수 있습니다.
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
또한 보다 명확하게 하기 위해 정적 메서드의 이름을 표준화했습니다.
예를 들어 fromXxx 와 같은 메소드 이름은 어댑터 로 사용할 때 사용되거나 미리 정의된 핸들러/가입자를 만들 때 ofXxx 와 같은 이름으로 사용됩니다 .
9.2. 일반적인 신체 유형을 위한 유창한 방법
생성된 게시자 및 일반적인 바디 유형을 처리하기 위한 핸들러를 위한 편리한 팩토리 메서드가 도입되었습니다.
예를 들어 바이트, 파일 및 문자열에서 게시자를 만드는 유창한 방법은 다음과 같습니다.
BodyPublishers.ofByteArray
BodyPublishers.ofFile
BodyPublishers.ofString
유사하게, 이러한 공통 바디 유형에서 핸들러를 생성하기 위해 다음을 사용할 수 있습니다.
BodyHandlers.ofByteArray
BodyHandlers.ofString
BodyHandlers.ofFile
9.3. 기타 API 변경 사항
1. 이 새로운 API를 사용하면 폐기(객체 교체) 대신 BodyHandlers.discarding() 및 BodyHandlers.replacing(값)을 사용할 것입니다 .
HttpResponse<?> response1 = HttpClient.newHttpClient()
.send(request, BodyHandlers.discarding());
HttpResponse<?> response1 = HttpClient.newHttpClient()
.send(request, BodyHandlers.replacing(value));
2. 새로운 방법 ofLines () 에 BodyHandlers가 첨가되는 라인의 스트림으로 응답 본체 스트리밍 처리.
3. fromLineSubscriber의 방법으로 첨가 BodyHandlers의 사이에 어댑터로서 사용될 수있다 클래스 BodySubscriber 및 텍스트 기반 Flow.Subscriber 선으로 텍스트 라인을 파싱한다.
4. BodySubscribers 클래스에 새로운 BodySubscriber.mapping 을 추가했습니다. 이 클래스는 주어진 기능을 본문 개체에 적용하여 한 Response body 유형에서 다른 Response body 유형으로 매핑하는 데 사용할 수 있습니다.
5. HttpClient.Redirect 에서 열거형 상수 SAME_PROTOCOL 및 SECURE 정책은 새로운 열거형 NORMAL 로 대체됩니다 .
10. HTTP/2에서 푸시 약속 처리하기
새로운 Http 클라이언트는 PushPromiseHandler 인터페이스를 통해 푸시 약속을 지원합니다 .
이를 통해 서버는 기본 리소스를 요청하는 동안 클라이언트에 추가 리소스를 "푸시"하여 더 많은 왕복을 절약할 수 있으며 결과적으로 페이지 렌더링 성능이 향상됩니다.
리소스 번들링을 잊게 해주는 것은 실제로 HTTP/2의 다중화 기능입니다. 각 리소스에 대해 서버는 푸시 약속이라고 하는 특별한 요청을 클라이언트에 보냅니다.
수신된 푸시 프라미스 가 있는 경우 지정된 PushPromiseHandler 에 의해 처리됩니다 . null 값 PushPromiseHnadler는 푸시 약속을 거부합니다.
HttpClient를는 과부하 가지고 가 SendAsync의 아래 예와 같이 우리가 이러한 약속을 처리 할 수 방법.
먼저 PushPromiseHandler를 생성해 보겠습니다 .
private static PushPromiseHandler<String> pushPromiseHandler() {
return (HttpRequest initiatingRequest,
HttpRequest pushPromiseRequest,
Function<HttpResponse.BodyHandler<String>,
CompletableFuture<HttpResponse<String>>> acceptor) -> {
acceptor.apply(BodyHandlers.ofString())
.thenAccept(resp -> {
System.out.println(" Pushed response: " + resp.uri() + ", headers: " + resp.headers());
});
System.out.println("Promise request: " + pushPromiseRequest.uri());
System.out.println("Promise request: " + pushPromiseRequest.headers());
};
}
다음으로 sendAsync 메서드를 사용 하여 이 푸시 약속을 처리해 보겠습니다 .
httpClient.sendAsync(pageRequest, BodyHandlers.ofString(), pushPromiseHandler())
.thenAccept(pageResponse -> {
System.out.println("Page response status code: " + pageResponse.statusCode());
System.out.println("Page response headers: " + pageResponse.headers());
String responseBody = pageResponse.body();
System.out.println(responseBody);
})
.join();
11. 결론
이 기사에서는 많은 유연성과 강력한 기능을 제공하는 Java 9의 HttpClient API를 살펴보았습니다 . Java 9의 HttpClient API에 사용되는 전체 코드는 GitHub에서 사용할 수 있습니다 .
또한 Java 9에 도입된 인큐베이팅 HttpClient를 보다 강력한 변경으로 표준화한 Java 11 HttpClient의 새로운 변경 사항을 살펴보았습니다. Java 11 Http Client에 사용되는 코드 조각은 Github 에서도 사용할 수 있습니다 .
참고: 예제에서는 https://postman-echo.com에서 제공하는 샘플 REST 끝점을 사용했습니다 .