[Spring] RestTemplate / spring 에서 http 통신하는 법 / API 호출
🐝 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 등)해서 제공
- 어플리케이션이 RestTemplate를 생성하고, URI, HTTP 메소드 등의 헤더를 담아 요청
- RestTemplate는 HttpMessageConverter를 사용하여 requestEntity를 요청 메세지로 변환
- RestTemplate는 ClientHttpRequestFactory로 부터 ClientHttpRequest를 가져와서 요청을 보냄
- ClientHttpRequest 는 요청메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신
- RestTemplate 는 ResponseErrorHandler 로 오류를 확인하고 있다면 처리로직을 태움
- ResponseErrorHandler 는 오류가 있다면 ClientHttpResponse 에서 응답데이터를 가져와서 처리
- RestTemplate 는 HttpMessageConverter 를 이용해서 응답메세지를 java object(Class responseType) 로 변환
- 어플리케이션에 반환
🐝 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);
... 생략
}
'web > Spring' 카테고리의 다른 글
[Spring JPA] Spring JPA에서 Cubrid(DBMS) 연결하는 법 (0) | 2022.01.04 |
---|---|
[Spring Boot] Flyway를 이용한 데이터 마이그레이션 / Spring DB Migration Tool flyway (0) | 2021.12.03 |
[Spring Mybatis] DB 조회, 수정, 삽입, 삭제 기능 구현 (0) | 2021.11.26 |
[JSP] formatNumber, formatDate 확장 태그 (2) | 2021.11.25 |
[Spring Web MVC] 컨트롤러 클래스, 뷰 구현 (2) | 2021.11.24 |
댓글 개