跳至主要内容

WebClient

Spring Webflux에는 reactive, non-blocking하게 HTTP요청을 처리할 수 있도록 WebClient 모듈을 제공

기존의 RestTemplate과 같은 역할이지만, non-blocking하다라는 차이가 있다.

내부적으로 WebClient는 HTTP 클라이언트 라이브러리에 위임하는데, 디폴트로 Reactor Netty의 HttpClient를 사용한다. Reactor Netty외에도, Jetty의 HttpClient를 지원하며, 다른 라이브러리도 ClientHttpConnector에 넣어주면 사용할 수 있다.


Setup the WebClient

create()

  • default WebClient
  • base URL
this.webClient = WebClient.create();
//or
this.webClient = WebClient.create("http://localhost:12345");

builder
this.webClient = WebClient.builder()
                          .baseUrl(properties.getHost())
                          .defaultHeader("Accept", MediaType.APPLICATION_JSON_VALUE,
                                         "Content-Type", MediaType.APPLICATION_JSON_VALUE
                          ).build();


Making calls

public Mono<ReturnedItem> callOne() {
    return webClient.get()
                    .uri("wait1")
                    .retrieve()
                    .bodyToMono(ReturnedItem.class);
}

public record ReturnedItem(UUID id, String info) {}
  • REST action
    • GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS의 helper method 제공됨
  • uri()
    • 호출 url, WebClient에서 설정한 baseUrl에 append 됨
  • retrieve
    • 실제 호출을 수행하고 호출을 설정하는 메서드에서 응답을 처리하는 메서드로 변환
  • bodyToMono
    • 원하는 payload를 제공

Request Body

retrieve()

response body를 가져오는 가장 단순한 방법이다. 오브젝트 stream을 Flux로 받을 수도 있다.

디폴트로, HTTP 응답 코드가 4xx, 5xx로 오면 WebClientResponseException이 발생한다. onStatus() 메소드를 통해 exception을 커스터마징할 수 있다.

Mono<Person> result = client.get()
            .uri("/persons/{id}", id).accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .onStatus(HttpStatus::is4xxServerError, response -> ...)
            .onStatus(HttpStatus::is5xxServerError, response -> ...)
            .bodyToMono(Person.class);

exchange()

retrieve()와 동일한 역할을 하면서 ClientResponse 객체의 접근을 가능하게 해 response 처리를 커스터마이징하기 보다 용이합니다.

Mono<Person> result = client.get()
            .uri("/persons/{id}", id).accept(MediaType.APPLICATION_JSON)
            .exchange()
            .flatMap(response -> response.bodyToMono(Person.class));

Mono형태의 객체를 request body에 넣을 수 있다.

Mono<Person> personMono = ... ;

    Mono<Void> result = client.post()
            .uri("/persons/{id}", id)
            .contentType(MediaType.APPLICATION_JSON)
            .body(personMono, Person.class)
            .retrieve()
            .bodyToMono(Void.class);
Flux<Person> personFlux = ... ;

    Mono<Void> result = client.post()
            .uri("/persons/{id}", id)
            .contentType(MediaType.APPLICATION_STREAM_JSON)
            .body(personFlux, Person.class)
            .retrieve()
            .bodyToMono(Void.class);


Mono나 Flux로 감싸지 않는 실제 오브젝트는 syncBody() 메소드로 넣을 수 있다.

Person person = ... ;

    Mono<Void> result = client.post()
            .uri("/persons/{id}", id)
            .contentType(MediaType.APPLICATION_JSON)
            .syncBody(person)
            .retrieve()
            .bodyToMono(Void.class);

form data를 넣고 싶으면 MultiValueMap형태로 body에 넣을 수 있다. 이 경우 자동으로 콘텐트 타입이 ‘application/x-www-form-urlencoded’로 셋팅된다.

MultiValueMap<String, String> formData = ... ;

    Mono<Void> result = client.post()
            .uri("/path", id)
            .syncBody(formData)
            .retrieve()
            .bodyToMono(Void.class);


[https://dreamchaser3.tistory.com/11](https://dreamchaser3.tistory.com/11] [https://tanzu.vmware.com/developer/guides/spring-webclient-gs/](https://tanzu.vmware.com/developer/guides/spring-webclient-gs/) [https://wedul.site/670](https://wedul.site/670) [https://lts0606.tistory.com/305](https://lts0606.tistory.com/305) [https://www.cognizantsoftvision.com/blog/getting-started-with-reactive-spring-spring-webflux/](https://www.cognizantsoftvision.com/blog/getting-started-with-reactive-spring-spring-webflux/)

评论

此博客中的热门博文

Pandas Plot

pandas.DataFrame.plot.bar import matplotlib.pyplot as plt import pandas as pd import numpy as np df = pd.DataFrame(np.random.rand(5, 4).round(1),                   index=['snail', 'pig', 'elephant','rabbit', 'giraffe'],                   columns=pd.Index(['speed', 'lifespan', 'active', 'cuite'],                   name='Genus')) ax = df.plot(kind='bar',figsize=(10,4), rot = 0) plt.show() ==> output in Pycharm

GIS

GIS 데이터 유형 Vector : 현실 세계를 점, 선, 면으로 표현  Raster : 현실 세계를 픽셀 단위로 표현 점, 선, 면을 Feature라 함 여러개의 Feature가 모이면 Dataset 여러개의 Dataset이 모이면 DataSource dataset은 geometry공간좌표(x, y)와 attribute로 구성 좌표계(coordinate system) 지리적인 데이터정보들을 통합하여 사용할 수 있도록 위치를 정해줌 좌표계의 종류 지리좌표체계 투영좌표체계 https://m.blog.naver.com/PostView.nhn?blogId=rsmilee&logNo=220651379673&proxyReferer=https%3A%2F%2Fwww.google.com%2F Pan 패닝: 마우스 움직임에 따라 해당되는 지도 영역이 보이는것? http://mcms.daegu.ac.kr/user/chodh/user_source/gis01.htm OpenStreetMap은  Mercator projection( "EPSG:3857" )을 사용 ol.proj.transform로 지리좌표( 경도 위도 ) 를  Mercator projection좌표계로 전환 축척 - 지도상에서 1유닛이 나타내는 거리값 Resolution(지도 해상도) - 현재 축척에서 1픽셀이 표현하는 거리값 https://www.muhanit.kr/%EA%B8%B0%EC%88%A0%EB%B8%94%EB%A1%9C%EA%B7%B8/openlayers%EC%9D%B4%EC%9A%A9-map%EC%9C%BC%EB%A1%9C%EB%B6%80%ED%84%B0-%EC%B6%95%EC%B2%99-%EA%B5%AC%ED%95%98%EA%B8%B0 Layer -  热度图层(heatmaplayer) 、 图片图层(imagelayer) 、 切片图层(tilelayer)  和...

Intellij DB Setting

  SQL Dialects → SQL 문법을 선택 파일 배경색 변경 quick documentation을 활용하자!