[SpringBoot] RestTemplate 이용하여 API 통신하기

오늘은 Spring 3.0부터 지원하며 Rest API의 통신을 할 수 있도록 도와주는

RestTemplate을 알아보도록 하겠다.

이전에 내가 포스팅한 [Java] REST API GET, POST 통신 예제를 통해서도

Rest API 통신을 할 수 있지만 오늘 소개할 RestTemplate을 이용하면 Spring에서 공식 지원하는 라이브러리라

좀 더 안정적이고 다양하며 방식으로 사용할 수 있다.

간단하게 Get 통신과 Post 통신을 예제로 통해 알아볼 것이고

Rest API 통신을 도와줄 http://jsonplaceholder.typicode.com/ 해당 홈페이지의 방식에 맞춰

데이터를 주고받을 것이다.

사전작업으로 POST통신시 Json 데이터 타입으로 으로 주고 받아 JSONObject가 필요함으로

아래의 라이브러리를 추가해준다.

implementation 'com.googlecode.json-simple:json-simple:1.1'

RestTemplate 객체 생성

public class RestTemplateMain {
    public static RestTemplate createRestTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(5000);    // 읽기시간초과, ms
        factory.setConnectTimeout(3000); // 연결시간초과, ms
        HttpClient httpClient = HttpClientBuilder.create()
            .setMaxConnTotal(100)   // connection pool 적용
            .setMaxConnPerRoute(5)  // connection pool 적용
            .build();
        factory.setHttpClient(httpClient); // 동기실행에 사용될 HttpClient 세팅
        return new RestTemplate(factory);
    }
}

기초적인 TimeOut과 Connetcion Pool을 설정해 주어 RestTemplate 객체를 만들어준다.

위와 같은 기초 설정을 하지 않아도 Default로 값을 만들어주니 필요에 따라서 값을 변경해서 사용하길 바란다.


Get 통신

GET /comments?postId=1 참고

public class RestTemplateMain {
    public static void main(String[] args) {
        getPost();
    }

    public static RestTemplate createRestTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(5000);    // 읽기시간초과, ms
        factory.setConnectTimeout(3000); // 연결시간초과, ms
        HttpClient httpClient = HttpClientBuilder.create()
            .setMaxConnTotal(100)   // connection pool 적용
            .setMaxConnPerRoute(5)  // connection pool 적용
            .build();
        factory.setHttpClient(httpClient); // 동기실행에 사용될 HttpClient 세팅
        return new RestTemplate(factory);
    }

    public static void getPost() {

        RestTemplate restTemplate = createRestTemplate();

        HttpEntity<?> httpEntity = new HttpEntity<>(null, null);

        String uri = "http://jsonplaceholder.typicode.com/comments";

        // Query Param 설정
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(uri)
                                                                        .queryParam("postId", 1);

        ResponseEntity <List<Map<String, Object>>> responseEntity = restTemplate.exchange(uriComponentsBuilder.build().encode().toUri(), HttpMethod.GET, httpEntity, new ParameterizedTypeReference <List<Map<String, Object>>> () {});

        System.out.println(responseEntity.getBody());
    }
}

여기서 하나 알아두면 좋은건 restTemplate의 exchage의 4번째 파라미터 Class responseType의 대해서이다.

만약의 기존의 방식이라면 Response Type Class에 대해서 단편적으로 선언하여 사용한다.

그러나 List<Map<String, Object>>까지만 해도 여러 클래스를 품고있어 List.class만으로 표현하기 힘들다.

기존의 방식대로 하면 다시 값을 꺼내어 캐스팅해줘야한다는 불편함이 존재한다.

ParameterizedTypeReference 해당 클래스를 이용하면 제네릭 타입 혹은 List<Map<String, Object>>같이 여러클래스를 내포하고있는 값도 표현해줄수있다.

변경전 : ResponseEntity responseEntity = restTemplate.exchange(uriComponentsBuilder.build().encode().toUri(), HttpMethod.GET, httpEntity, List.class);

변경후 : ResponseEntity<List<Map<String, Object>>> responseEntity = restTemplate.exchange(uriComponentsBuilder.build().encode().toUri(), HttpMethod.GET, httpEntity, new ParameterizedTypeReference <List<Map<String, Object>>> () {});

위와같이 API 통신 하면 아래와 같은 값이 리턴된다.

Response

[
  {
    "postId": 1,
    "id": 1,
    "name": "id labore ex et quam laborum",
    "email": "Eliseo@gardner.biz",
    "body": "laudantium enim quasi est quidem magnam voluptate ipsam eos\ntempora quo necessitatibus\ndolor quam autem quasi\nreiciendis et nam sapiente accusantium"
  },
  {
    "postId": 1,
    "id": 2,
    "name": "quo vero reiciendis velit similique earum",
    "email": "Jayne_Kuhic@sydney.com",
    "body": "est natus enim nihil est dolore omnis voluptatem numquam\net omnis occaecati quod ullam at\nvoluptatem error expedita pariatur\nnihil sint nostrum voluptatem reiciendis et"
  },
  {
    "postId": 1,
    "id": 3,
    "name": "odio adipisci rerum aut animi",
    "email": "Nikita@garfield.biz",
    "body": "quia molestiae reprehenderit quasi aspernatur\naut expedita occaecati aliquam eveniet laudantium\nomnis quibusdam delectus saepe quia accusamus maiores nam est\ncum et ducimus et vero voluptates excepturi deleniti ratione"
  },
  {
    "postId": 1,
    "id": 4,
    "name": "alias odio sit",
    "email": "Lew@alysha.tv",
    "body": "non et atque\noccaecati deserunt quas accusantium unde odit nobis qui voluptatem\nquia voluptas consequuntur itaque dolor\net qui rerum deleniti ut occaecati"
  },
  {
    "postId": 1,
    "id": 5,
    "name": "vero eaque aliquid doloribus et culpa",
    "email": "Hayden@althea.biz",
    "body": "harum non quasi et ratione\ntempore iure ex voluptates in ratione\nharum architecto fugit inventore cupiditate\nvoluptates magni quo et"
  }
]

Post 통신

public class RestTemplateMain {
    public static void main(String[] args) {
        postPost();
    }

    public static RestTemplate createRestTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(5000);    // 읽기시간초과, ms
        factory.setConnectTimeout(3000); // 연결시간초과, ms
        HttpClient httpClient = HttpClientBuilder.create()
            .setMaxConnTotal(100)   // connection pool 적용
            .setMaxConnPerRoute(5)  // connection pool 적용
            .build();
        factory.setHttpClient(httpClient); // 동기실행에 사용될 HttpClient 세팅
        return new RestTemplate(factory);
    }

    public static void postPost() {

        RestTemplate restTemplate = createRestTemplate();

        // Http Header 설정
        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.APPLICATION_JSON);

        // Http Body 설정
        JSONObject bodyParam = new JSONObject();

        bodyParam.put("title", "Rest");
        bodyParam.put("body", "Teamplte");
        bodyParam.put("userId", 1);

        HttpEntity <?> httpEntity = new HttpEntity <>(bodyParam, header);

        String uri = "http://jsonplaceholder.typicode.com/posts";

        // Query Param 설정
        UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(uri);

        ResponseEntity<Map> responseEntity = restTemplate.exchange(uriComponentsBuilder.build().encode().toUri(), HttpMethod.POST, httpEntity, Map.class);

        System.out.println(responseEntity.getBody());
    }
}

Post 통신에서는 Response Type을 ParameterizedTypeReference를 이용하지않고

Map.class를 이용하여 작업하였다.

Response

{
  "id": 101,
  "title": "Rest",
  "body": "Teamplte",
  "userId": 1
}

정상적으로 POST 통신을 한 것을 볼 수 있다.

규칙성을 가지고 RestTemplate를 이용한다면 보다 보기 좋고 효율성 있는 코드를 표현할 수 있다.

다른 글 읽어보기 ⬇️