본문 바로가기
카테고리 없음

외부 API 호출하는 RestTemplate 사용하려면

by 문자메일 2023. 7. 1.

 

1. 아래 코드처럼 RestTemplate() 인스턴스를 다른 클래스에서 주입받아서 사용할 수 있게 스프링 빈으로 등록한다.

import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class JpashopApplication {

	...
    
	@Bean
	public RestTemplate getRestTemplate(){
		return new RestTemplate();
	}

}

 

2. 주입받은 restTemplate.exchange() 메서드로 외부 API를 호출하고, 결과 응답을 받는다.

 

MessageConverter에서 java object를 request body에 담을 message로 변환하거나, 서버로부터 전달받은 message를 java object로 변환해서 응답해주는 역할을 한다.

 

그래서  아래 코드에서 Restemplate.exchange() 메서드에서 ResponseEntity, ParameterizedTypeReference 클래스의 제네릭 부분에 상대 서버에서 전달받은 데이터의 클래스에 해당하는 클래스 정보를 입력한 것이다.

package jpabook.jpashop.controller;

import jpabook.jpashop.api.MemberApiController;
import jpabook.jpashop.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
@RequestMapping(value = "/rest")
public class RestTemplateController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private Environment environment;

    @GetMapping("/get1")
    public ResponseEntity<List<Member>> getMethod1(){
        String testUrl = environment.getProperty("rest-template.get1");

        ResponseEntity<List<Member>> members =
                restTemplate.exchange(testUrl, HttpMethod.GET, null,
                new ParameterizedTypeReference<List<Member>>() {
        });

        return members;
    }

    @GetMapping("/get2")
    public ResponseEntity<MemberApiController.Result<List<MemberApiController.MemberDto>>> getMethod2(){
        String testUrl = environment.getProperty("rest-template.get2");

        ResponseEntity<MemberApiController.Result<List<MemberApiController.MemberDto>>> members =
        restTemplate.exchange(testUrl, HttpMethod.GET, null,
                new ParameterizedTypeReference<MemberApiController.Result<List<MemberApiController.MemberDto>>>() {
                });

        return members;
    }
}

 

application.yaml

rest-template:
  get1: http://localhost:8080/api/v1/members
  get2: http://localhost:8080/api/v2/members

 

외부 api

    @GetMapping("/api/v1/members")
    public List<Member> membersV1(){
        return memberService.findMembers();
    }

    @GetMapping("/api/v2/members")
    public Result memberV2(){
        List<Member> findMembers = memberService.findMembers();
        List<MemberDto> collect = findMembers.stream()
                .map(m-> new MemberDto(m.getName()))
                .collect(Collectors.toList());

        return new Result<List<MemberDto>>(collect.size(), collect);
    }

 

 

====================================================

 

아래는 HttpComponentsClientHttpRequestFactory라는 팩토리 클래스까지 만들어서, 커넥션 타임아웃 설정, 커넥션 풀 설정 등 까지 지정하고, 위 예시와 다르게 자바 Object가 아니라 Map.class로 응답 받아 Response 하는 메서드임.

 

    @GetMapping("/get3")
    public HashMap<String, Object> getMethod3(){

        // 0. 결과값을 담을 객체를 생성합니다.
        HashMap<String, Object> resultMap = new HashMap<String, Object>();

        String testUrl = environment.getProperty("rest-template.get2");

        try{
//            HttpComponentsClientHttpRequestFactory
            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
            factory.setConnectTimeout(5000); // 타임아웃 설정 5초
            factory.setReadTimeout(5000); // 타임아웃 설정 5초

            HttpClient httpClient = HttpClientBuilder.create()
                    .setMaxConnTotal(50)
                    .setMaxConnPerRoute(20)
                    .build();

            factory.setHttpClient(httpClient);

            // 2. RestTemplate 객체를 생성한다.
            RestTemplate restTemplate = new RestTemplate(factory);

            // 3. header 설정을 위해 HttpHeader 클래스를 생성하고, HttpEntity 객체에 넣어준다.
            HttpHeaders header = new HttpHeaders();
            HttpEntity<String> entity = new HttpEntity<String>(header);

            // 4. 요청 URL을 정의해준다.
            String url = "api 요청 URL";
            UriComponents uri = UriComponentsBuilder.fromHttpUrl(testUrl).build(false);

            // 5. exchange() 메소드로 api를 호출한다.
            ResponseEntity<Map> response = restTemplate.exchange(uri.toString(), HttpMethod.GET, entity, Map.class);

            // 6. 요청한 결과를 HashMap에 추가한다.
            // HTTP Status Code
            resultMap.put("statusCode", response.getStatusCodeValue());
            // 헤더 정보
            resultMap.put("header", response.getHeaders());
            // 반환받은 실제 데이터 정보
            resultMap.put("body", response.getBody());
        } catch(Exception e){
            e.printStackTrace();
        }

        return resultMap;
    }

 

아래는 서버 호출하여 응답받은 json 값

{
  "header": {
    "Content-Type": [
      "application/json"
    ],
    "Transfer-Encoding": [
      "chunked"
    ],
    "Date": [
      "Sat, 01 Jul 2023 05:41:31 GMT"
    ],
    "Keep-Alive": [
      "timeout=60"
    ],
    "Connection": [
      "keep-alive"
    ]
  },
  "body": {
    "count": 2,
    "data": [
      {
        "name": "userA"
      },
      {
        "name": "userB"
      }
    ]
  },
  "statusCode": 200
}

댓글