Languages/Kotlin

[Kotlin] Open API 호출해서 데이터 가져오기

반응형

알파버전 프로젝트에 코틀린을 적용해보자는 이야기가 나와서 코틀린을 들여다 보느라 하루가 다 갔다. 우선 외부 데이터를 끌어다가 출력하는것까지 시도했다. 다른 분이 자바로 예제를 올려두신 걸 보고 코틀린으로 옮겨 적었다. 너무 옮겨적은 것 같으니 프로젝트 진행하면서는 좀 갈고 닦아봐야 할 것 같다.

▼ 우선 gradle에 dependency를 설정했다. 

dependencies {
	implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
	implementation("org.springframework.boot:spring-boot-starter-web")
	implementation("org.springframework.boot:spring-boot-starter-web-services")
	implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
	implementation("org.jetbrains.kotlin:kotlin-reflect")
	implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
	implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
	testImplementation("org.springframework.boot:spring-boot-starter-test")

	compileOnly("com.fasterxml.jackson.core:jackson-core:2.9.3")
	compileOnly("com.fasterxml.jackson.core:jackson-databind:2.9.3")
	compileOnly("com.google.code.gson:gson:2.8.5")
	compileOnly("com.googlecode.json-simple:json-simple:1.1.1")

	implementation("org.apache.httpcomponents:httpclient:4.5")
}

 

▼ RestAPI 소스코드.

package com.kotlin.ktDemo

import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.http.*
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.client.HttpClientErrorException
import org.springframework.web.client.HttpServerErrorException
import org.springframework.web.client.RestTemplate
import org.springframework.web.util.UriComponents
import org.springframework.web.util.UriComponentsBuilder
import kotlin.collections.HashMap

@RestController
class RestAPI {

    @GetMapping("/getKobisData")
    private fun callAPI() : String {

        val result  = HashMap<String, Any>()
        var jsonInString = ""

        try {
            val factory = HttpComponentsClientHttpRequestFactory();

            factory.setConnectTimeout(5000)
            factory.setReadTimeout(5000)

            val restTemplate = RestTemplate(factory)
            //restTemplate은 Rest방식 api를 호출할 수 있는 spring 내장 클래스이다.
            //json, xml 응답을 모두 받을 수 있다.

            //header 클래스를 정의해 주고, url을 정의해 주고 exchange method로 api를 호출한다.
            val header = HttpHeaders()
            //header.contentType= MediaType.parseMediaType("application/json")

            val entity = HttpEntity<Map<String, Any>>(header)
            val url = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json"
            val uri : UriComponents
                    = UriComponentsBuilder.fromHttpUrl(url + "?" + "key=827c3342e912bdb8cdbeb7cf0625b764&targetDt=20210430").build()
           
            //api를 호출하여 데이터를 MAP타입으로 전달 받는다.
            val resultMap : ResponseEntity<Map<*, *>>
                    = restTemplate.exchange(uri.toString(), HttpMethod.GET, entity, Map::class.java)

            result.put("statusCode", resultMap.getStatusCodeValue()); //http status code를 확인
            result.put("header", resultMap.getHeaders()); //헤더 정보 확인
            resultMap.body?.let { result.put("body", it) }; 
            //result.put("body", resultMap.getBody())로 넣을 수 없었다. null 가능성 때문인 것 같다.

            //데이터를 string형태로 파싱해줌
            val mapper = ObjectMapper()
            jsonInString = mapper.writeValueAsString(resultMap.getBody());

        } catch (e: Exception){
            when(e) {
                is HttpClientErrorException, is HttpServerErrorException -> {
                    result.put("statusCode", "e.getStatusCode()"); //여기랑
                    result.put("body", "e.getStatusText()"); //여기는 kotlin에서 오류가 났다. 그래서 함수를 그냥 따옴표로 감싸버림.. 확인 필요
                    System.out.println("error!");
                    System.out.println(e.toString());
                }else -> {
                	result.put("statusCode", "999");
                	result.put("body", "excpetion오류");
                	System.out.println(e.toString());
            	}
            }
        }

        return jsonInString;
    }
}

 

▼ 대망의 실행결과

 

▼ 그리고 요즘 겪는 이상한 현상... 프로젝트를 돌리면 똥골뱅이들이 멈추지 않고 계속 돌아간다. 켜두고 나갔다 오니까 1시간 45분이 넘도록 계속 돌고 있었음. 결과 화면은 잘 뜨는데 멈추지 않으니까 찝찝하다. 이건 뭐라고 검색해야 나올까? 아시는 분이 있으시다면 댓글 부탁드립니다.

 

▼ 나를 수시간 애먹였던 Java Reflection. 알아야 검색도 잘 할 수 있다... 나의 지난 눈물겨운 삽질.

Java reflection works on Kotlin classes and vice versa. As mentioned above, you can use instance::class.java, ClassName::class.java or instance.javaClass to enter Java reflection through java.lang.Class. Do not use ClassName.javaClass for this purpose because it refers to ClassName 's companion object class, which is the same as ClassName.Companion::class.java and not ClassName::class.java.
For each primitive type, there are two different Java classes, and Kotlin provides ways to get both. For example, Int::class.java will return the class instance representing the primitive type itself, corresponding to Integer.TYPE in Java. To get the class of the corresponding wrapper type, use Int::class.javaObjectType, which is equivalent of Java's Integer.class.
Other supported cases include acquiring a Java getter/setter method or a backing field for a Kotlin property, a KProperty for a Java field, a Java method or constructor for a KFunction and vice versa.
 

Calling Java from Kotlin | Kotlin

 

kotlinlang.org

 

예제를 참고한 블로그 포스팅. 

 

[Springboot] Resttemplate으로 api호출하기 (ex,영진위 데이터 호출 resttemplate.exchange 활용)

오늘은 springboot를 기반으로 웹서버를 생성한 후 API를 호출해 데이터를 전달 받아 화면에 출력해보도록 하겠습니다. Springboot 기본 설정은 아래 URL에서 확인 부탁드립니다. 인텔리J에서 Springboot

vmpo.tistory.com

 

Java Reflection에 대해 상세하게 정리해둔 블로그 포스팅.

 

[코틀린] 코틀린의 리플렉션(Reflection)

리플렉션(Reflection)은 런타임 때 프로그램의 구조(객체, 함수, 프로퍼티)를 분석해 내는 기법을 이야기합니다. 코틀린에서 리플렉션을 위해서는 라이브러리가 필요합니다. kotlin-reflect.jar 라는

kyyeto.tistory.com

 

728x90
반응형