네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

🐝  Rest 서비스를 호출하는 방법

- RestTemplate 

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

- AsyncRestTemplate

Spring 4에 추가된 비동기 RestTemplate

- WebClient

Spring 5에 추가된 논블록, 리액티브 웹 클라이언트로 동기, 비동기 방식을 지원

 

🐝  RestTemplate이란?

- spring 3.0 부터 지원

- 스프링에서 제공하는 http 통신에 사용할 수 있는 템플릿

- HTTP 서버와의 통신을 단순화하고 RESTful 원칙을 지킨다. (json, xml을 응답받을 수 있음)

 

🐝  RestTemplate 메서드

메서드 HTTP 설명
getForObject GET 주어진 URL 주소로 HTTP GET 메서드로 객체로 결과를 반환받는다.
getForEntity GET 주어진 URL 주소로 HTTP GET 메서드로 ReponseEntity로 결과를 반환받는다.
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 콜백을 수정할 수 있다.

 

🐝  초기화

기본 생성자는 java.net.HttpURLConnection 라이브러리를 사용한다. ClientHttpRequestFactory를 사용하여 다른 HTTP 라이브러리로 바꿀 수 있다. 스프링은 Apache HttpComponents, Netty, OkHttp를 지원한다.

예)

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

각 ClientHttpRequestFactory는 기본 HTTP 클라이언트 라이브러리에 대한 구성 옵션을 제공한다. 주의할 점은 java.net 패키지의 HTTP 구현체를 사용할 경우 401 상태를 가진 응답 객체에 접근할 때 Exception이 발생할 수 있으므로, 이럴 경우 다른 HTTP 라이브러리를 사용해야 한다.

 

🐝  URIs

대부분의 RestTemplate 메서드는 String vararg 또는 Map<String, String>을 통해 URI 템플릿과 URI 템플릿 변수를 허용한다.

// String vararg
String result = restTemplate.getForObject("http:example.com/hotels/{hotel}/bookings/{booking}", String.class, "102", "1204");

// Map<String, String>
Map<String, String> vars = Collections.singletonMap("hotel", "102");
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}", String.class, vars);

URI 템플릿은 자동으로 인코딩된다.

restTemplate.getForObject("http://example.com/hotel list", String.class);
// 요청 url: "http://example.com/hotel%20list"

RestTemeplate의 uriTemplateHandler 속성을 사용해 URI 인코딩 방법을 지정할 수 있다. 또는 java.net.URI를 사용하여 RestTemplate 메서드에 인자로 전달할 수 있다.

 

🐝  Headers

exchange() 메서드를 사용해 요청 헤더를 지정할 수 있다.

String uriTemplate = "http://example.com/hotels/{hotel}"
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(102);

RequestEntity<Void> requestEntity = RequestEntity.get(uri)
    .header("MyRequestHeader", "MyValue")
    .build();
    
ResponseEntity<String> response = template.exchange(requestEntity, String.class);

String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();

ResponseEntity를 반환하는 RestTemplate의 여러 메서드를 통해 응답 헤더를 얻을 수 있다.

 

🐝  RestTemplate 동작 원리

- HTTP Client는 HTTP를 사용하여 통신하는 범용 라이브러리

- RestTemplate는 HTTPClient를 추상화(HttpEntity의 json, xml 등)해서 제공

 

  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. 어플리케이션에 반환

🐝  RestTemplate 사용 예제

조건

- 비동기 방식으로 POST 메서드를 사용해 log를 저장해야 함. => AsyncRestTemplate JSONObject로 값 전달

- 다른 API 사용 => url 사용

    public static void insertLog(HttpServletRequest request, String memberId, String publicDataPk) {
        String url = "http://localhost:8080/logs";
        
        AsyncRestTemplate restTemplate = new AsyncRestTemplate(); // 비동기 전달
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("memberId", memberId);
        jsonObject.put("sessionId", request.getRequestedSessionId());
        jsonObject.put("publicDataId", publicDataId);

        HttpEntity<String> logRequest = new HttpEntity<>(jsonObject.toString(), httpHeaders);
        restTemplate.postForEntity(url, logRequest, String.class);
        
        ... 생략
    }

 

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !