-
RestTemplate Get Request - RestTemplate Hands On 2Spring Framework/RestTemplate 2023. 9. 21. 00:01
개요
이전의 RestTemplate 생성과정에 이어 RestTemplate Get Request를 실습해보려 합니다.
글에서는 다음과 같은 테스트를 수행해 봅니다.
- Get으로 String 객체 호출해 보기
- getForEntity와 getForObject의 차이점
- String을 returnType으로 받지만 MyObject가 오는 경우
- 내가 원하는 필드만 발라내기
- 중첩 객체 필드도 받을 수 있는가
외부 호출 Controller 준비
@RestController class TestController { @GetMapping("/outer-call") fun outerCall(): String{ sleep(1000) return "process 1s job" } } // intellij HTTP plugin을 활용하여 호출해보기 // GET localhost:8080/outer-call
getForEntity 활용해서 외부 호출하기
@GetMapping("/test") fun test(): String{ val baseUrl = "http://localhost:8080" val apiPath = "/outer-call" val restTemplate = RestTemplate() val response: ResponseEntity<String> = restTemplate.getForEntity( baseUrl + apiPath, String::class.java, ) println(response.statusCode) println(response.headers) println(response.body) return "hello" } // intellij HTTP plugin을 활용하여 호출해보기 // GET localhost:8080/test //결과 //200 OK //[Content-Type:"text/plain;charset=UTF-8", Content-Length:"14", Date:"Fri, 01 Sep 2023 11:57:59 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"] //process 1s job
RestTemplate 메서드의 getForEntity()를 활용하여 url과 responseType을 넣어 response를 원하는 타입으로 얻을 수 있습니다.
응답 결과인 ResponseEntity<String>의 결과를 출력해 보면 순차적으로 statusCode에 대한 결과, 헤더에 대한 정보, body에 대한 정보를 얻을 수 있습니다.
body의 값으로는 outer-call을 호출했을 때 반환하는 process 1s job이 그대로 반환됩니다.
getForEntity 메서드 내부
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException { RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); }
내부적으로는 HTTPMethod.GET 인자를 넘겨서 execute 메서드를 호출해 주는 모습을 볼 수 있습니다.
getForEntity vs getForObject
val responseByGetForObject: String? = restTemplate.getForObject( baseUrl + apiPath, String::class.java, ) println(responseByGetForObject)
getForObject는 getForEntity와 다르게 헤더정보나 status 정보가 없습니다.
String으로 responseType을 받으려 하지만 MyObject가 반환되는 경우
data class MyObject( val col1: String = "col1", val col2: String = "col2", val col3: String = "col3", ) @GetMapping("/object-outer-call") fun objectOuterCall(): ResponseEntity<MyObject>{ sleep(1000) return ResponseEntity.ok(MyObject()) }
MyObject를 선언하고 MyObject 타입으로 반환하도록 object-outer-call api를 구현합니다.
이제 String Type으로 받게 되면 어떻게 될까요?
개인적으로는 타입이 맞지 않아 에러가 날것이라고 생각했습니다.
@GetMapping("/object-test") fun objectTest(): String{ val baseUrl = "http://localhost:8080" val apiPath = "/object-outer-call" val restTemplate = RestTemplate() val response: ResponseEntity<String> = restTemplate.getForEntity( baseUrl + apiPath, String::class.java, ) println(response.statusCode) println(response.body) return "hello" } //결과 //200 OK //{"col1":"col1","col2":"col2","col3":"col3"}
하지만 결과는 Stirng으로 잘 보입니다.
String 대신 MyObject로 반환받는 경우
val response: ResponseEntity<MyObject> = restTemplate.getForEntity( baseUrl + apiPath, MyObject::class.java, ) //결과 //200 OK //MyObject(col1=col1, col2=col2, col3=col3)
String 클래스 대신 MyObject 클래스로 받는 경우에는 형변환까지 자동으로 됩니다.
여기까지 되자 2가지 궁금증이 생겼습니다.
- 내가 관심 있는 필드만 받는 것도 가능할까? (예를 들어 col1 ... col100까지 있는데 나는 col2, col3 만 관심이 있는 경우)
- 객체내부에서 객체를 가지는 경우도 잘 받아질까?
바로 테스트해 보겠습니다.
내가 관심 있는 필드만 받아 보기
data class _MyObject( val col2: String = "col2", ) val response: ResponseEntity<_MyObject> = restTemplate.getForEntity( baseUrl + apiPath, _MyObject::class.java, ) //MyObject -> _MyObject로 변환 //결과 //200 OK //_MyObject(col2=col2)
호출하는 쪽에서는 col2에만 관심이 있다고 _MyObject 클래스를 col2 만 가지도록 해보았습니다.
결과로는 _MyObject에 col2에 대한 부분만 매핑이 잘 된 모습을 볼 수 있습니다.
객체내부에서 객체를 가지는 중첩 구조도 잘 받아질까?
val response: ResponseEntity<_NestedMyObject> = restTemplate.getForEntity( baseUrl + apiPath, _NestedMyObject::class.java, ) data class _NestedMyObject( val nestedMyObject2: _NestedMyObject2, val test: String, ) data class _NestedMyObject2( val nestedCol2: String, ) data class NestedMyObject( val nestedMyObject2: NestedMyObject2 = NestedMyObject2(), val test: String = "nestedTest", ) data class NestedMyObject2( val nestedCol1: String = "nestedCol1", val nestedCol2: String = "nestedCol2", ) //결과 //200 OK //_NestedMyObject(nestedMyObject2=_NestedMyObject2(nestedCol2=nestedCol2), test=nestedTest)
NestedMyObject라는 클래스를 만들었고 받는 쪽에서는 _NestedMyObject2 클래스의 필드하나까지 생략해 보았습니다 (위에서 이미 테스트해 보긴 했음)
중첩된 구조도 잘 받아지는 것을 확인할 수 있습니다.
마무리
Get에 대한 응답을 어떻게 받을지 다루어 보았습니다.
다음글으로는 Get을 호출할 때 활용할 QueryParam, PathVariable에 대해 알아보고자 합니다.
참고자료
https://www.baeldung.com/rest-template
'Spring Framework > RestTemplate' 카테고리의 다른 글
RestTemplate Timeout - ResetTemplate Hands On 7 (0) 2023.09.28 RestTemplate Error Handling - RestTemplate Hands On 6 (0) 2023.09.27 RestTemplate Post Request - RestTemplate Hands On 4 (0) 2023.09.24 RestTemplate Get Request - RestTemplate Hands On 3 (0) 2023.09.23 RestTemplate이란? - RestTemplate Hands On 1 (0) 2023.09.20