안녕하세요.
컨씨브이개발자입니다.
Java Spring프레임워크 기반의 시스템을 다루다보면 REST API를 호출받거나
호출하는 일은 받느시 알아둬야한다. 그래서 오늘은 REST API호출할 때의 방식과
HTTPS의 경우엔 어떠한지, 호출할 때 요청할 값을 파라미터에 넣는 방법 등을 알아보겠다.
1. 일반적인 HttpURLConnection 사용
먼저 REST API이란 것은 간단하게 URL에 데이터를 담아 외부시스템으로 전송하는 것으로 보면된다.
보내는 방식에는 대표적으로 GET, POST 방식이 있으며 보통 JSON형태로 묶어서 보낸다.
먼저 HttpURLConnection과 URL 클래스를 사용하는 예시이다.
String callUrl = "해당 URL 입력 (https://~~)";
URL url = new URL(callUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
위 코드와 같이 연결할 URL에 openConnection을 이용하여 연결할 준비를 합니다.
//httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestMethod("POST");
연결할 방식으로 대표적인 GET, POST 방식으로 메소드 셋팅을 합니다.
int responseCode = httpURLConnection.getResponseCode();
다음 코드를 통해 연결 응답 값을 받아올 수 있는데, 이 값이 200인 경우만 정상으로 보면된다.
InputStreamReader in = new InputStreamReader(httpURLConnection.getInputStream(), "UTF-8");
String response = IOUtils.toString(in);
if( null != in ){
in.close();
}
getInputStream() 함수를 사용하여 정상적으로 호출이 되었을 경우 호출 시의 값 데이터를 받아올 수 있습니다.
저 같은 경우엔 JSON데이터를 많이 받기 때문에 String response의 값이 JSON형태로 들어가 있을 텐데,
이럴땐 ObjectMapper를 사용하여 변환할 수 있다.
HashMap<String, Object> responseBody = new HashMap<>();
ObjectMapper objectMapper = new ObjectMapper()
responseBody = objectMapper.readValue(response, HashMap.class);
자세한 내용은 아래 JSON데이터 변환을 확인해주기 바란다.
https://jiwoong-java.tistory.com/2
[JAVA] JSON 데이터 HashMap에 담는 방법
안녕하세요. 컨씨브이개발자입니다. Java Spring프레임워크 기반의 시스템을 다루면서 DB 컬럼에 들어있는 JSON 값이나 REST API를 통해 받아온 JSON 데이터를 다시 DB에 적재하거나 화면에 보여주기 위
jiwoong-java.tistory.com
2. 파라미터를 담아 호출하는 경우
URL을 호출할 때 파라미터를 실어서 보내야할 경우가 있다.
예를 들어 어떤 기준일자의 데이터만 가져오고 싶을 경우 param -> {"req_date":"20230429"} 와 같이 담는다.
아래 예제 코드를 확인해주기 바란다.
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("req_date","20230429");
//헤더에 Content-Type을 json형태로 추가함.
httpURLConnection.addRequestProperty(HTTP.CONTENT_TYPE, "application/json");
//출력스트림 열고닫기 GET방식은 false, POST방식은 true
httpURLConnection.setDoOutput(true);
//URL에 파라미터 담기
DataOutputStream dataOutputStream = new DataOutputStream(httpURLConnection.getOutputStream());
if( paramMap != null){
dataOutputStream.writeBytes(objectMapper.writeValueAsString(paramMap);
}
dataOutputStream.flush();
dataOutputStream.close();
4번 라인에 파라미터를 어떤 형식으로 요청할지 Content-Type 타입을 설정해준다 addRequestProperty 함수를 사용하여
HTTP.CONTENT_TYPE ( "Content-Type" ) 을 json 형태로 헤더에 추가해준다.
6번 라인에 setDoOutPut 함수가 있는데, 이것은 출력스트림을 열고 닫는 것이다. GET방식의 경우엔 URL 뒤에 ? 붙여 파라미터를 붙일 수 있지만, POST 방식은 URL뒤에 붙이는게 아니라 직접 스트림에 담아 보내야하기 때문이다.
마지막으로 DataOutputStream을 통해 파라미터(해쉬맵)를 objectMapper를 통해 바이트(Byte)단위로 출력스트림에 담아 보낸다.
3. 인증토큰을 사용해야하는 경우
호출받는 시스템측에서 인증토큰도 넣어달라는 경우가 있는데, 당황하지 말고 헤더에 인증토큰을 추가하면된다.
String ACCESS_TOKEN = "상대 시스템에서 제공하는 인증토큰";
httpURLConnection.setRequestProperty("Authorization", ACCESS_TOKEN);
4. https SSL보안 인증을 우회해야하는 경우
이 부분은 구글링해보면 많이 나오고 정해진 소스 부분이 있는 것으로 보인다.
아래는 제가 사용하는 코드이다.
TrustManager[] trustAllcerts = new TrustManager[] {
new javax.net.ssl.X509TrustManager () {
public java.security.cert.X509Certificate[] getAcceptedIssuers(){
return null;
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException{
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException{
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
5. 최종 코드
아래에는 제가 실무에서 사용하는
- https호출
- POST방식
- JSON요청
- 인증토큰
- List형JSON데이터 받기
다섯가지를 다 사용한 전체 코드입니다.
public static List<HashMap<String, Object>> callHttpsPost (String callUrl, HashMap<String, Object> paramMap, String authorization) throws Exception {
List<HashMap<String, Object>> responseBody = new ArrayList<HashMap<String, Object>>();
ObjectMapper objectMapper = new ObjectMapper();
//SSL https 호출 관련
TrustManager[] trustAllCerts = new TrustManager[] {
new javax.net.ssl.X509TrustManager () {
public java.security.cert.X509Certificate[] getAcceptedIssuers(){
return null;
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException{
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException{
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
// callUrl 파라미터 받아서 넣는 부분
URL url = new URL(callUrl);
// 인증토큰 파라미터 받아서 넣는 부분
String ACCESS_TOKEN = authorization;
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
//POST방식
httpURLConnection.setRequestMethod("POST");
if(!"".equals(ACCESS_TOKEN)){
httpURLConnection.setRequestProperty("Authorization", ACCESS_TOKEN);
}
//json방식 헤더에 추가
httpURLConnection.addRequestProperty(HTTP.CONTENT_TYPE, "application/json");
//POST 방식 요청 파라미터 출력 스트림 열기
httpURLConnection.setDoOutput(true);
DataOutputStream dataOutputStream = new DataOutputStream(httpURLConnection.getOutputStream());
//요청 파라미터 바이트 단위로 넣기
if( paramMap != null){
dataOutputStream.writeBytes(objectMapper.writeValueAsString(paramMap);
}
//
dataOutputStream.flush();
dataOutputStream.close();
//실패가 났는지 확인하기 위해 응답코드 받아보기
int responseCode = httpURLConnection.getResponseCode();
System.out.println("responseCode ::: "+responseCode);
InputStreamReader in = new InputStreamReader(httpURLConnection.getInputStream(), "UTF-8");
//요청해서 들어온 데이터 String에 넣기
String response = IOUtils.toString(in);
if( null != in ) {
in.close();
}
//List형태의 JSON 데이터를 변환하는 작업
responseBody = objectMapper.readValue(response, new TypeReference<List<HashMap<String, Object>>>(){});
return responseBody;
}
위 코드를 참고하여 GET방식으로 호출하거나, 파라미터를 보내지 않는다거나, 받는 데이터형식을 변경할 수 있다.
위 코드에서 대용량 데이터를 받았을 경우
조금이라도 더 빠르게 구현될 수 있는 코드가 있으면 알려주시면 감사하겠습니다.
'JAVA' 카테고리의 다른 글
[JAVA] foreach문의 몰랐던 사실 HashMap(참조? 주소값?) (0) | 2023.05.07 |
---|---|
[JAVA] JSON 데이터 HashMap에 담는 방법 (0) | 2023.04.08 |