1. 개요

이 튜토리얼에서는 Spring REST 클라이언트 인 RestTemplate을 사용하고 잘 사용할 수있는 광범위한 작업을 설명합니다 .

모든 예제의 API 측에서는 여기 에서 RESTful 서비스를 실행합니다 .

2. 지원 중단 알림

Spring Framework 5부터 WebFlux 스택과 함께 Spring은 WebClient 라는 새로운 HTTP 클라이언트를 도입했습니다 .

WebClient  는 RestTemplate에 대한 최신 대체 HTTP 클라이언트 입니다. 기존의 동기식 API를 제공 할뿐만 아니라 효율적인 비 차단 및 비동기 접근 방식도 지원합니다.

즉, 새 애플리케이션을 개발하거나 이전 애플리케이션을 마이그레이션하는 경우 WebClient 를 사용하는 것이 좋습니다  . 앞으로 RestTemplate  은 향후 버전에서 더 이상 사용되지 않습니다.

3. GET을 사용하여 리소스 검색

3.1. 일반 JSON 가져 오기

getForEntity () API 를 사용하는 간단한 예제를 통해 간단하게 시작하고 GET 요청에 대해 이야기하겠습니다 .

RestTemplate restTemplate = new RestTemplate();
String fooResourceUrl
  = "http://localhost:8080/spring-rest/foos";
ResponseEntity<String> response
  = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));

HTTP 응답에 대한 전체 액세스 권한이 있으므로 상태 코드를 확인하여 작업이 성공했는지 확인하거나 응답의 실제 본문과 함께 작업하는 것과 같은 작업을 수행 할 수 있습니다.

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response.getBody());
JsonNode name = root.path("name");
assertThat(name.asText(), notNullValue());

여기서는 Response body을 표준 문자열로 사용하고 Jackson (및 Jackson이 제공하는 JSON 노드 구조)을 사용하여 세부 정보를 확인하고 있습니다.

3.2. JSON 대신 POJO 검색

응답을 리소스 DTO에 직접 매핑 할 수도 있습니다.

public class Foo implements Serializable {
    private long id;

    private String name;
    // standard getters and setters
}

이제 템플릿에서 getForObject API를 간단히 사용할 수 있습니다 .

Foo foo = restTemplate
  .getForObject(fooResourceUrl + "/1", Foo.class);
assertThat(foo.getName(), notNullValue());
assertThat(foo.getId(), is(1L));

4. HEAD를 사용하여 헤더 검색

이제보다 일반적인 방법으로 넘어 가기 전에 HEAD 사용을 간단히 살펴 보겠습니다.

우리는 사용하게 될 겁니다 ) (headForHeaders을 여기 API를 :

HttpHeaders httpHeaders = restTemplate.headForHeaders(fooResourceUrl);
assertTrue(httpHeaders.getContentType().includes(MediaType.APPLICATION_JSON));

5. POST를 사용하여 리소스 만들기

API에서 새 리소스를 생성하기 위해 postForLocation () , postForObject () 또는 postForEntity () API를 잘 사용할 수 있습니다 .

첫 번째는 새로 생성 된 리소스의 URI를 반환하고 두 번째는 리소스 자체를 반환합니다.

5.1. postForObject () API

RestTemplate restTemplate = new RestTemplate();

HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class);
assertThat(foo, notNullValue());
assertThat(foo.getName(), is("bar"));

5.2. postForLocation () API

마찬가지로 전체 리소스를 반환하는 대신 새로 생성 된 리소스 위치 만 반환하는 작업을 살펴 ​​보겠습니다 .

HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
URI location = restTemplate
  .postForLocation(fooResourceUrl, request);
assertThat(location, notNullValue());

5.3. 교환 () API

보다 일반적인 교환 API를 사용하여 POST를 수행하는 방법을 살펴 보겠습니다 .

RestTemplate restTemplate = new RestTemplate();
HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"));
ResponseEntity<Foo> response = restTemplate
  .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
 
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
 
Foo foo = response.getBody();
 
assertThat(foo, notNullValue());
assertThat(foo.getName(), is("bar"));

5.4. 양식 데이터 제출

다음으로 POST 메서드를 사용하여 양식을 제출하는 방법을 살펴 보겠습니다.

먼저 Content-Type 헤더를 application / x-www-form-urlencoded로 설정해야합니다.

이렇게하면 &로 구분 된 이름 / 값 쌍을 포함하는 큰 쿼리 문자열을 서버로 보낼 수 있습니다 .

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

양식 변수를 LinkedMultiValueMap 으로 래핑 할 수 있습니다 .

MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("id", "1");

다음 으로 HttpEntity 인스턴스를 사용하여 요청을 작성  합니다 .

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

마지막으로 끝점에서 restTemplate.postForEntity ()호출하여 REST 서비스에 연결할 수 있습니다  / foos / form

ResponseEntity<String> response = restTemplate.postForEntity(
  fooResourceUrl+"/form", request , String.class);
 
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

6. OPTIONS를 사용하여 허용 된 작업 얻기

다음으로 OPTIONS 요청을 사용하고 이러한 종류의 요청을 사용하여 특정 URI에서 허용되는 작업을 탐색하는 방법을 간략하게 살펴 보겠습니다. API는 optionsForAllow입니다 .

Set<HttpMethod> optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl);
HttpMethod[] supportedMethods
  = {HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE};
assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));

7. PUT를 사용하여 리소스 업데이트

다음으로, template.put API가 매우 간단하기 때문에 PUT와 좀 더 구체적 으로이 작업에 대한 exchange () API를 살펴 보겠습니다 .

7.1. 간단한 PUT교환 ()

API에 대한 간단한 PUT 작업으로 시작하겠습니다.이 작업은 본문을 클라이언트로 다시 반환하지 않습니다.

Foo updatedInstance = new Foo("newName");
updatedInstance.setId(createResponse.getBody().getId());
String resourceUrl = 
  fooResourceUrl + '/' + createResponse.getBody().getId();
HttpEntity<Foo> requestUpdate = new HttpEntity<>(updatedInstance, headers);
template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class);

7.2. exchange () 및 요청 콜백이있는 PUT

다음으로 요청 콜백을 사용하여 PUT를 발행 할 것입니다.

필요한 모든 헤더와 요청 본문을 설정할 수있는 콜백을 준비해야합니다.

RequestCallback requestCallback(final Foo updatedInstance) {
    return clientHttpRequest -> {
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(clientHttpRequest.getBody(), updatedInstance);
        clientHttpRequest.getHeaders().add(
          HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        clientHttpRequest.getHeaders().add(
          HttpHeaders.AUTHORIZATION, "Basic " + getBase64EncodedLogPass());
    };
}

다음으로 POST 요청으로 리소스를 생성합니다.

ResponseEntity<Foo> response = restTemplate
  .exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
assertThat(response.getStatusCode(), is(HttpStatus.CREATED));

그런 다음 리소스를 업데이트합니다.

Foo updatedInstance = new Foo("newName");
updatedInstance.setId(response.getBody().getId());
String resourceUrl =fooResourceUrl + '/' + response.getBody().getId();
restTemplate.execute(
  resourceUrl, 
  HttpMethod.PUT, 
  requestCallback(updatedInstance), 
  clientHttpResponse -> null);

8. DELETE를 사용하여 리소스 제거

기존 리소스를 제거하기 위해 delete () API를 빠르게 사용할 것입니다 .

String entityUrl = fooResourceUrl + "/" + existingResource.getId();
restTemplate.delete(entityUrl);

9. 시간 초과 구성

ClientHttpRequestFactory 를 사용하여 RestTemplate 을 시간 초과 하도록 구성 할 수 있습니다 .

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
      = new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(timeout);
    return clientHttpRequestFactory;
}

추가 구성 옵션에 HttpClient사용할 수 있습니다.

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    RequestConfig config = RequestConfig.custom()
      .setConnectTimeout(timeout)
      .setConnectionRequestTimeout(timeout)
      .setSocketTimeout(timeout)
      .build();
    CloseableHttpClient client = HttpClientBuilder
      .create()
      .setDefaultRequestConfig(config)
      .build();
    return new HttpComponentsClientHttpRequestFactory(client);
}

10. 결론

이 기사에서는 RestTemplate 을 사용하여 이들 모두를 사용하여 요청을 오케스트레이션 하는 주요 HTTP 동사에 대해 살펴 보았습니다 .

템플릿으로 인증을 수행하는 방법에 대해 자세히 알아 보려면 RestTemplate을 사용한 기본 인증 에 대한 기사를 확인하십시오 .

이러한 모든 예제 및 코드 스 니펫의 구현은 GitHub 에서 찾을 수 있습니다 .