ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RestTemplate & WebClient
    STUDY/백엔드 2021. 2. 3. 18:57

    1. RestTemplate

     - Spring 3부터 지원 되었고 REST API 호출이후 응답을 받을 때까지 기다리는 동기방식이다.

     - Blocking I/O 기반의 Synchronous API (순서가 있는 처리)

    • 스프링 부트는 Rest Template을 쉽게 사용할 수 있도록 빈을 등록해준다.
    • 이때 빈은 RestTemplateBuilder를 빈으로 등록해 준다.
    • Builder를 주입받아서 필요시마다 Build를 하고 RestClient를 생성해서 사용할 수 있다.

     

     

    1. 어플리케이션이 RestTemplate를 생성하고, URI, HTTP메소드 등의 헤더를 담아 요청한다.
    2. RestTemplate 는 HttpMessageConverter 를 사용하여 requestEntity 를 요청메세지로 변환한다.
    3. RestTemplate 는 ClientHttpRequestFactory 로 부터 ClientHttpRequest 를 가져와서 요청을 보낸다.
    4. ClientHttpRequest 는 요청메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신한다.
    5. RestTemplate 는 ResponseErrorHandler 로 오류를 확인하고 있다면 처리로직을 태운다.
    6. ResponseErrorHandler 는 오류가 있다면 ClientHttpResponse 에서 응답데이터를 가져와서 처리한다.
    7. RestTemplate 는 HttpMessageConverter 를 이용해서 응답메세지를 java object(Class responseType) 로 변환한다.
    8. 어플리케이션에 반환된다.
    getForObject GET 주어진 URL 주소로 HTTP GET 메서드로 객체로 결과를 반환받는다
    getForEntity GET 주어진 URL 주소로 HTTP GET 메서드로 결과는 ResponseEntity로 반환받는다
    postForLocation POST POST 요청을 보내고 결과로 헤더에 저장된 URI를 결과로 반환받는다
    postForObject POST POST 요청을 보내고 객체로 결과를 반환받는다
    postForEntity POST POST 요청을 보내고 결과로 ResponseEntity로 반환받는다
    delete DELETE 주어진 URL 주소로 HTTP DELETE 메서드를 실행한다
    headForHeaders HEADER 헤더의 모든 정보를 얻을 수 있으면 HTTP HEAD 메서드를 사용한다
    put PUT 주어진 URL 주소로 HTTP PUT 메서드를 실행한다
    patchForObject PATCH 주어진 URL 주소로 HTTP PATCH 메서드를 실행한다
    optionsForAllow OPTIONS 주어진 URL 주소에서 지원하는 HTTP 메서드를 조회한다
    exchange any HTTP 헤더를 새로 만들 수 있고 어떤 HTTP 메서드도 사용가능하다
    execute any Request/Response 콜백을 수정할 수 있다

    - 사용 예시

    restTemplate.exchange(url, HttpMethod, HttpEntity, Response type, PathVariables);


    2. AsyncRestTemplate

     - Spring 4에 추가된 비동기 RestTemplate이다.

     - Spring 5.0에서는 deprecated 되었다.

     

    3. WebClient

     - Spring 5에 추가된 논블럭, 리엑티브 웹 클리이언트로 동기, 비동기 방식을 지원한다.

     - Non-Blocking I/O 기반의 Asynchronous API(순서가 없는 처리)

    • WebClient는 WebClient.Builder를 빈으로 등록해준다.
    • WebClient를 사용하기 위해서는 webflux 의존성을 넣어주어야 한다.

     

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

     

    - Builder 패턴 사용해서 인스턴스 만들기

    Webclient client = WebClient
                              .builder()
                              .baseUrl("http://localhost:8080")
                              .defaultCookie("쿠키키","쿠키값")
                              .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)                                  .build();

     

    - GET

    webClient
      .mutate()
      .baseUrl("https://localhost:8080/api")
      .build()
      .get()
      .uri("/test?id={ID}", id)
      .accept(MediaType.APPLICATION_JSON)
      .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
      .retrieve()
      .bodyToMono(SomeData.class) ;

     

    - POST

    webClient
      .mutate()
      .baseUrl("https://localhost:8080/api")
      .build()
      .post()
      .uri("/login")
      .contentType(MediaType.APPLICATION_JSON)
      .accept(MediaType.APPLICATION_JSON)
      .bodyValue(loginInfo)
      .retrieve()
      .bodyToMono(SomeData.class);

     

    - PUT

    webClient
      .mutate()
      .baseUrl("https://localhost:8080/api")
      .build()
      .put()
      .uri("/test/{ID}", id)
      .contentType(MediaType.APPLICATION_JSON)
      .accept(MediaType.APPLICATION_JSON)
      .bodyValue(someData)
      .retrieve()
      .bodyToMono(SomeData.class);

     

    - DELETE

    webClient
      .mutate()
      .baseUrl("https://localhost:8080/api")
      .build()
      .delete()
      .uri("/test/{ID}", id)
      .retrieve()
      .bodyToMono(Void.class);

     

    - HTTP 호출 결과를 가져오는 방법에는 retrieve()와 exchange() 방법이 있다. retrieve()를 사용하면 ResponseBody를 처리할 수 있고, exchange()를 사용하면 세세하게 Response 컨텐츠에 대한 처리가 가능하다. 하지만 exchange()는 모든 처리를 직접하면서 발생할 수 있는 memory leak 가능성 때문에 가급적 retrieve() 사용을 권고한다.

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

     

    - 4XX and 5XX 처리

    webClient
      .mutate()
      .baseUrl("https://localhost:8080")
      .build()
      .get()
      .uri("/test")
      .accept(MediaType.APPLICATION_JSON)
      .retrieve()
      .onStatus(status -> status.is4xxClientError() || status.is5xxServerError()
                 , clientResponse -> clientResponse.bodyToMono(String.class)
                                                              .map(body->new RuntimeException(body)))
      .bodyToMono(SomeData.class)

     

    출처 : advenoh.tistory.com/46, 

            https://sjh836.tistory.com/141,

            medium.com/@odysseymoon/spring-webclient-%EC%82%AC%EC%9A%A9%EB%B2%95-5f92d295edc0

    'STUDY > 백엔드' 카테고리의 다른 글

    Spring Batch  (0) 2021.03.03
    메모리 영역  (0) 2021.02.08
    @Mock, @MockBean  (0) 2021.02.03
    @ControllerAdvice / @RestControllerAdvice  (0) 2021.02.03
    Bean  (0) 2021.01.05
Designed by Tistory.