Loading...
Spring Framework Reference Documentation 7.0.2의 Configuration의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
WebClient를 생성하는 가장 간단한 방법은 다음과 같은 static 팩토리 메서드를 사용하는 것입니다:
WebClient.create()WebClient.create(String baseUrl)또한 추가 옵션과 함께 WebClient.builder()를 사용할 수도 있습니다:
uriBuilderFactory: 기본 URL로 사용할 커스터마이즈된 UriBuilderFactory.defaultUriVariables: URI 템플릿을 확장할 때 사용할 기본 값들.defaultHeader: 모든 요청에 대한 헤더.defaultCookie: 모든 요청에 대한 쿠키.defaultApiVersion: 모든 요청에 대한 API 버전.defaultRequest: 모든 요청을 커스터마이즈하기 위한 Consumer.filter: 모든 요청에 대한 클라이언트 필터.exchangeStrategies: HTTP 메시지 리더/라이터 커스터마이제이션.clientConnector: HTTP 클라이언트 라이브러리 설정.apiVersionInserter: 요청에 API 버전 값을 삽입하기 위한 옵션observationRegistry: Observability support를 활성화하기 위해 사용할 레지스트리.observationConvention: 기록된 observation에 대한 메타데이터를 추출하기 위한 선택적, 커스텀 컨벤션.예시는 다음과 같습니다:
1WebClient client = WebClient.builder() 2 .codecs(configurer -> ... ) 3 .build(); 4Copied!
1val webClient = WebClient.builder() 2 .codecs { configurer -> ... } 3 .build() 4Copied!
한번 build된 WebClient는 immutable입니다. 그러나 다음과 같이 clone하여 수정된 복사본을 build할 수 있습니다:
1WebClient client1 = WebClient.builder() 2 .filter(filterA).filter(filterB).build(); 3 4WebClient client2 = client1.mutate() 5 .filter(filterC).filter(filterD).build(); 6 7// client1 has filterA, filterB 8 9// client2 has filterA, filterB, filterC, filterD 10Copied!
1val client1 = WebClient.builder() 2 .filter(filterA).filter(filterB).build() 3 4val client2 = client1.mutate() 5 .filter(filterC).filter(filterD).build() 6 7// client1 has filterA, filterB 8 9// client2 has filterA, filterB, filterC, filterD 10Copied!
Codec은 애플리케이션의 메모리 이슈를 피하기 위해 메모리에서 데이터를 버퍼링하는 데 대한 제한을 가집니다. 기본적으로 이는 256KB로 설정되어 있습니다.
그것으로 충분하지 않다면 다음과 같은 에러를 보게 됩니다:
org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer
기본 코덱에 대한 제한을 변경하려면 다음을 사용하십시오:
1WebClient webClient = WebClient.builder() 2 .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024)) 3 .build(); 4Copied!
1val webClient = WebClient.builder() 2 .codecs { configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024) } 3 .build() 4Copied!
Reactor Netty 설정을 커스터마이즈하려면, 미리 설정된 HttpClient를 제공하십시오:
1HttpClient httpClient = HttpClient.create().secure(sslSpec -> ...); 2 3WebClient webClient = WebClient.builder() 4 .clientConnector(new ReactorClientHttpConnector(httpClient)) 5 .build(); 6Copied!
1val httpClient = HttpClient.create().secure { ... } 2 3val webClient = WebClient.builder() 4 .clientConnector(ReactorClientHttpConnector(httpClient)) 5 .build() 6Copied!
기본적으로, HttpClient는 이벤트 루프 스레드와 커넥션 풀을 포함하는
reactor.netty.http.HttpResources에 보관된 전역 Reactor Netty 리소스에 참여합니다.
이는 이벤트 루프 동시성을 위해 고정된 공유 리소스가 선호되므로 권장되는 모드입니다.
이 모드에서 전역 리소스는 프로세스가 종료될 때까지 활성 상태로 유지됩니다.
서버가 프로세스와 함께 타이밍되는 경우, 일반적으로 명시적인 종료가 필요하지 않습니다.
그러나 서버가 프로세스 내에서 시작되거나 중지될 수 있는 경우(예: WAR로 배포된 Spring MVC
애플리케이션), Spring이 관리하는 ReactorResourceFactory 타입의 빈을
globalResources=true(기본값)로 선언하여 Spring ApplicationContext가 닫힐 때
Reactor Netty 전역 리소스가 종료되도록 할 수 있습니다. 다음 예시와 같습니다:
1@Bean 2public ReactorResourceFactory reactorResourceFactory() { 3 return new ReactorResourceFactory(); 4} 5Copied!
1@Bean 2fun reactorResourceFactory() = ReactorResourceFactory() 3Copied!
또한 전역 Reactor Netty 리소스에 참여하지 않도록 선택할 수도 있습니다. 그러나 이 모드에서는 다음 예시와 같이 모든 Reactor Netty 클라이언트 및 서버 인스턴스가 공유 리소스를 사용하도록 보장해야 하는 책임이 있습니다:
1@Bean 2public ReactorResourceFactory resourceFactory() { 3 ReactorResourceFactory factory = new ReactorResourceFactory(); 4 factory.setUseGlobalResources(false); (1) 5 return factory; 6} 7 8@Bean 9public WebClient webClient() { 10 11 Function<HttpClient, HttpClient> mapper = client -> { 12 // Further customizations... 13 }; 14 15 ClientHttpConnector connector = 16 new ReactorClientHttpConnector(resourceFactory(), mapper); (2) 17 18 return WebClient.builder().clientConnector(connector).build(); (3) 19} 20Copied!
| 1 | 전역 리소스와 독립적인 리소스를 생성합니다. |
| 2 | 리소스 팩토리와 함께 ReactorClientHttpConnector 생성자를 사용합니다. |
| 3 | 커넥터를 WebClient.Builder에 연결합니다. |
1@Bean 2fun resourceFactory() = ReactorResourceFactory().apply { 3 isUseGlobalResources = false (1) 4} 5 6@Bean 7fun webClient(): WebClient { 8 9 val mapper: (HttpClient) -> HttpClient = { 10 // Further customizations... 11 } 12 13 val connector = ReactorClientHttpConnector(resourceFactory(), mapper) (2) 14 15 return WebClient.builder().clientConnector(connector).build() (3) 16} 17Copied!
| 1 | 전역 리소스와 독립적인 리소스를 생성합니다. |
| 2 | 리소스 팩토리와 함께 ReactorClientHttpConnector 생성자를 사용합니다. |
| 3 | 커넥터를 WebClient.Builder에 연결합니다. |
커넥션 타임아웃을 설정하려면:
1import io.netty.channel.ChannelOption; 2 3HttpClient httpClient = HttpClient.create() 4 .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000); 5 6WebClient webClient = WebClient.builder() 7 .clientConnector(new ReactorClientHttpConnector(httpClient)) 8 .build(); 9Copied!
1import io.netty.channel.ChannelOption 2 3val httpClient = HttpClient.create() 4 .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000); 5 6val webClient = WebClient.builder() 7 .clientConnector(ReactorClientHttpConnector(httpClient)) 8 .build(); 9Copied!
read 또는 write 타임아웃을 설정하려면:
1import io.netty.handler.timeout.ReadTimeoutHandler; 2import io.netty.handler.timeout.WriteTimeoutHandler; 3 4HttpClient httpClient = HttpClient.create() 5 .doOnConnected(conn -> conn 6 .addHandlerLast(new ReadTimeoutHandler(10)) 7 .addHandlerLast(new WriteTimeoutHandler(10))); 8 9// Create WebClient... 10Copied!
1import io.netty.handler.timeout.ReadTimeoutHandler 2import io.netty.handler.timeout.WriteTimeoutHandler 3 4val httpClient = HttpClient.create() 5 .doOnConnected { conn -> conn 6 .addHandlerLast(ReadTimeoutHandler(10)) 7 .addHandlerLast(WriteTimeoutHandler(10)) 8 } 9 10// Create WebClient... 11Copied!
모든 요청에 대한 response 타임아웃을 설정하려면:
1HttpClient httpClient = HttpClient.create() 2 .responseTimeout(Duration.ofSeconds(2)); 3 4// Create WebClient... 5Copied!
1val httpClient = HttpClient.create() 2 .responseTimeout(Duration.ofSeconds(2)); 3 4// Create WebClient... 5Copied!
특정 요청에 대한 response 타임아웃을 설정하려면:
1WebClient.create().get() 2 .uri("https://example.org/path") 3 .httpRequest(httpRequest -> { 4 HttpClientRequest reactorRequest = httpRequest.getNativeRequest(); 5 reactorRequest.responseTimeout(Duration.ofSeconds(2)); 6 }) 7 .retrieve() 8 .bodyToMono(String.class); 9Copied!
1WebClient.create().get() 2 .uri("https://example.org/path") 3 .httpRequest { httpRequest: ClientHttpRequest -> 4 val reactorRequest = httpRequest.getNativeRequest<HttpClientRequest>() 5 reactorRequest.responseTimeout(Duration.ofSeconds(2)) 6 } 7 .retrieve() 8 .bodyToMono(String::class.java) 9Copied!
다음 예시는 JDK HttpClient를 커스터마이즈하는 방법을 보여줍니다:
1HttpClient httpClient = HttpClient.newBuilder() 2 .followRedirects(Redirect.NORMAL) 3 .connectTimeout(Duration.ofSeconds(20)) 4 .build(); 5 6ClientHttpConnector connector = 7 new JdkClientHttpConnector(httpClient, new DefaultDataBufferFactory()); 8 9WebClient webClient = WebClient.builder().clientConnector(connector).build(); 10Copied!
1val httpClient = HttpClient.newBuilder() 2 .followRedirects(Redirect.NORMAL) 3 .connectTimeout(Duration.ofSeconds(20)) 4 .build() 5 6val connector = JdkClientHttpConnector(httpClient, DefaultDataBufferFactory()) 7 8val webClient = WebClient.builder().clientConnector(connector).build() 9Copied!
다음 예시는 Jetty HttpClient 설정을 커스터마이즈하는 방법을 보여줍니다:
1HttpClient httpClient = new HttpClient(); 2httpClient.setCookieStore(...); 3 4WebClient webClient = WebClient.builder() 5 .clientConnector(new JettyClientHttpConnector(httpClient)) 6 .build(); 7Copied!
1val httpClient = HttpClient() 2httpClient.cookieStore = ... 3 4val webClient = WebClient.builder() 5 .clientConnector(JettyClientHttpConnector(httpClient)) 6 .build() 7Copied!
기본적으로, HttpClient는 프로세스가 종료되거나 stop()이 호출될 때까지 활성 상태로 유지되는
자체 리소스(Executor, ByteBufferPool, Scheduler)를 생성합니다.
여러 Jetty 클라이언트(및 서버) 인스턴스 간에 리소스를 공유하고 Spring ApplicationContext가
닫힐 때 리소스가 종료되도록 보장하려면, 다음 예시와 같이 Spring이 관리하는
JettyResourceFactory 타입의 빈을 선언하십시오:
1@Bean 2public JettyResourceFactory resourceFactory() { 3 return new JettyResourceFactory(); 4} 5 6@Bean 7public WebClient webClient() { 8 9 HttpClient httpClient = new HttpClient(); 10 // Further customizations... 11 12 ClientHttpConnector connector = 13 new JettyClientHttpConnector(httpClient, resourceFactory()); (1) 14 15 return WebClient.builder().clientConnector(connector).build(); (2) 16} 17Copied!
| 1 | 리소스 팩토리와 함께 JettyClientHttpConnector 생성자를 사용합니다. |
| 2 | 커넥터를 WebClient.Builder에 연결합니다. |
1@Bean 2fun resourceFactory() = JettyResourceFactory() 3 4@Bean 5fun webClient(): WebClient { 6 7 val httpClient = HttpClient() 8 // Further customizations... 9 10 val connector = JettyClientHttpConnector(httpClient, resourceFactory()) (1) 11 12 return WebClient.builder().clientConnector(connector).build() (2) 13} 14Copied!
| 1 | 리소스 팩토리와 함께 JettyClientHttpConnector 생성자를 사용합니다. |
| 2 | 커넥터를 WebClient.Builder에 연결합니다. |
다음 예시는 Apache HttpComponents HttpClient 설정을 커스터마이즈하는 방법을 보여줍니다:
1HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom(); 2clientBuilder.setDefaultRequestConfig(...); 3CloseableHttpAsyncClient client = clientBuilder.build(); 4 5ClientHttpConnector connector = new HttpComponentsClientHttpConnector(client); 6 7WebClient webClient = WebClient.builder().clientConnector(connector).build(); 8Copied!
1val client = HttpAsyncClients.custom().apply { 2 setDefaultRequestConfig(...) 3}.build() 4val connector = HttpComponentsClientHttpConnector(client) 5val webClient = WebClient.builder().clientConnector(connector).build()
WebClient
retrieve()