티스토리 뷰

 

[ 1. Open API ] (*****)

 

[ 1 - 1. 네이버에서 응답 받아와 보기 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.javastd;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;

import lombok.extern.log4j.Log4j2;


@Log4j2
public class HttpURLConnectionExample {
	
	public static void main(String[] args) throws Exception {
		log.trace("main({}) invoked.", Arrays.toString(args));
		
		// ========================================
		// 1. 지정된 url 주소로 URL 객체 생성하기
		// ========================================
		
		URL url = new URL("https://www.naver.com/");
		log.info("\t + 1. url : {}", url);
		// + 1. url : https://www.naver.com/
		// + URL을 잘못입력할 경우  MalformedURLException 예외가 발생한다.
		
		// ==========================================
		// 2. URL 객체에서 URLConnection 객체를 획득
		// ==========================================
		
		URLConnection conn = url.openConnection();
		log.info("\t + 2. conn type : {}", conn.getClass().getName());
		// + 2. conn type : sun.net.www.protocol.https.HttpsURLConnectionImpl
		
		// =================================================
		// 3. URLConnection 객체를 자식타입으로 강제형변환
		// =================================================
		
		HttpURLConnection httpConn = (HttpURLConnection) conn;	// + HTTP Client 역할을 한다.
		
		// =======================================================================================================
		// 4. HttpURLConnection 객체를 통해서, HTTP request(요청메세지)를 보내고 HTTP response(응답메세지)를 받자
		// =======================================================================================================
		// + 이때 요청과 응답은 InputStream과 OutputStream을 통해서 수행한다.
		// =======================================================================================================
		
		InputStream is = httpConn.getInputStream();		// + 바이트 기반의 입력스트림 획득
		
		// httpConn.getOutputStream();
		// + 나로부터 응답 메세지를 보내는 것이 아니라, url에서 받기만 할 예정이기에 InputStream만 필요
		
		int b;
		
		while ( ( b = is.read() ) != -1 ) { // + EOF : ( End Of File )
			
			System.out.print( (char) b);
			// + url에서 보내오는 것은 거대한 문자열이기에 char타입으로 변환하여 받아야 한다.
			
		} // while
		
		is.close();		// + 자원 해제
		
	} // main

} // end class

 

[ 1 - 2. 공공 데이터 포털의 Open API 활용 1 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.javastd;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Arrays;

import lombok.Cleanup;
import lombok.extern.log4j.Log4j2;


@Log4j2
public class HttpURLConnectionExample2 {
	
	public static void main(String[] args) throws Exception {
		log.trace("main({}) invoked.", Arrays.toString(args));
		
		// =======================================================================================================
		// 1. 지정된 url 주소로 URL 객체 생성하기
		// =======================================================================================================
		// + 승인받은 공공데이터 포털의 endpoint로 URL을 생성하고, 전송파라미터도 쿼리 String 형태로 붙여준다.
		// =======================================================================================================
		
		// ===============================================
		// 1 ) 방법 1
		// ===============================================
		String endPoint = "http://openapi.data.go.kr/openapi/service/rest/Covid19/getCovid19InfStateJson";
		String params = "?serviceKey=k%2FpKmqc79MTVkMiYnlv2rLFvpKZ12SLF5sbbTZhIZM135W7670MN9Oz89apgMp%2FGWnzhH1js2Yw%39D%3D"+
						"&pageNo=1"+
						"&numOfRows=10"+
						"&startCreateDt=20220801"+
						"&endCreateDt=20220830";
		
		String apiUrl = endPoint + params;
		
		// ===============================================
		// 2 ) 방법 2
		// ===============================================
		StringBuffer sb = new StringBuffer();
		sb.append("http://openapi.data.go.kr/openapi/service/rest/Covid19/getCovid19InfStateJson");
		sb.append("?serviceKey=k%2FpKmqc79MTVkMiYnlv2rLFvpKZ12SLF5sbbTZhIZM135W7670MN9Oz89apgMp%2FGWnzhH1js2Yw%39D%3D");
		sb.append("&pageNo=1");
		sb.append("&numOfRows=10");
		sb.append("&startCreateDt=20220801");
		sb.append("&endCreateDt=20220830");

		// + 만약, 전송파라미터 값 중에 다국어 문자 등이 있을 경우에는 반드시! URL Encoding을 해서 넣어줘야 한다.
		// + ex. sb.append(URLEncoder.encode("값", "utf8")); (****)
		
		String apiUrl2 = sb.toString();
		
		URL url = new URL(apiUrl2);
		log.info("\t + 1. url : {}", url);
		
		// ==========================================
		// 2. URL 객체에서 URLConnection 객체를 획득
		// ==========================================
		
		URLConnection conn = url.openConnection();
		
		// ==========================================
		// + 추가적인 설정
		// ==========================================
		conn.setConnectTimeout(1000 * 1);		// 연결시간 - 밀리세컨드 단위
		conn.setReadTimeout(1000*2);			// 읽어오는 시간 - 밀리세컨드 단위
		conn.setDoInput(true);					// InputStream을 사용할 것이다
		conn.setDoOutput(false);				// OutputStream을 사용하지 않을 것이다.
		
		// =================================================
		// 3. URLConnection 객체를 자식타입으로 강제형변환
		// =================================================
		
		@Cleanup("disconnect")
		HttpURLConnection httpConn = (HttpURLConnection) conn;	// + HTTP Client 역할을 한다.
		
		// ==========================================
		// + 추가적인 설정 (***)
		// ==========================================
		httpConn.setRequestMethod("GET");						// + GET 방식으로 요청 메세지를 보내겠다.
		httpConn.setConnectTimeout(1000 * 1);					// + 연결시간 - 밀리세컨드 단위
		httpConn.setReadTimeout(1000*2);						// + 읽어오는 시간 - 밀리세컨드 단위
		httpConn.setDoInput(true);								// + InputStream을 사용할 것이다
		httpConn.setDoOutput(false);							// + OutputStream을 사용하지 않을 것이다.
		
		// =======================================================================================================
		// 4. HttpURLConnection 객체를 통해서, HTTP request(요청메세지)를 보내고 HTTP response(응답메세지)를 받자
		// =======================================================================================================
		// + 이때 요청과 응답은 InputStream과 OutputStream을 통해서 수행한다.
		// + 이 단계에서 자동으로 request
		// =======================================================================================================
		
		if ( httpConn.getResponseCode() == HttpURLConnection.HTTP_OK ) {
			
			log.info("\t + >>>> httpConn.getResponseCode : {} <<<< ", httpConn.getResponseCode());
			
			// ===========================================================================
			// + HttpURLConnection과 InputStream을 차례대로 닫게 하기 위해서,
			// + InputStream을 블록 안에 넣어, 블록의 끝에 도달하면 먼저 닫히게 하였다.
			// ===========================================================================	
			
			@Cleanup
			InputStream is = conn.getInputStream();		
			// + 바이트 기반의 입력스트림 획득
			// + InputStream을 얻는 동시에 요청을 보내게 된다.
			
			int b;
			
			while ( ( b = is.read() ) != -1 ) { // + EOF : ( End Of File )
				
				System.out.print( (char) b);
				// + url에서 보내오는 것은 거대한 문자열이기에 char타입으로 변환하여 받아야 한다.
				
			} // while
			
		} // if : 상태코드가 OK일때만 읽어 들인다.
		
	} // main

} // end class

[ 2. XML 문서 parsing하기 - Dom4j ] (***)

 

[ 2 - 1. pom.xml 파일에 디펜던시 추가 ]

 

더보기

[ + 코드 보기 ]

      <!-- ================ XML Parsing ================= -->
      <dependency>
         <groupId>org.dom4j</groupId>
         <artifactId>dom4j</artifactId>
         <version>2.1.3</version>
      </dependency>

 

[ 2 - 2. resources 폴더 밑에 xml 파일 넣기 ]

 

 

[ 2 - 3. Dom4j 활용하기 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.dom4j;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;

import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@NoArgsConstructor
@Log4j2

@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Dom4jTests {
	
	// @Disabled
	@Test
	@Order(1)
	@DisplayName("Step 1. readXML")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void readXML() throws DocumentException {
		
		log.trace("readXML() invoked.");
		
		// ========================================
		// 1. XML SAX Parser 생성 
		// ========================================
		
		SAXReader reader = new SAXReader();
		log.info("\t + 1. SAXReader : {}", reader);
		
		// ====================================================
		// 2. XML 파일 읽어오기 
		// + XML SAX Parser을 통해 파싱 수행 -> DOM tree 생성
		// ====================================================
		
		reader.setEncoding("utf8");
		// + 최근에는 기본으로 utf8로 지정되어있으나, 혹시 모르니 지정해줘야 한다.
		
		Document doc = reader.read("src/main/resources/Covid19DailyState.xml");
		// + 파일의 경로( = systemId )를 url형태로 작성해 준다.
		
		log.info("\t + 2. Document : {}", doc);
		// + 2. Document : org.dom4j.tree.DefaultDocument@efde75f [Document: name src/main/resources/Covid19DailyState.xml]
		// + 실제 타입이 다른 것을 보아 Document는 인터페이스임을 알 수 있다.
		// + 어느 경로의 파일을 읽고 있는지도 출력해 준다.
		
		// ========================================
		// 3. 문서 객체에 대한 정보 출력
		// ========================================
		
		log.info("\t + 3-1. docType : {}",doc.getDocType());
		// + 3-1. docType : null
		
		log.info("\t + 3-2. name : {}", doc.getName());
		// + 3-2. name : src/main/resources/Covid19DailyState.xml
		
		log.info("\t + 3-3. XMLEncoding : {}", doc.getXMLEncoding());
		// + 3-3. XMLEncoding : UTF8
		
		// ========================================
		// 4. DOM 순회
		// ========================================
		
		Element root = doc.getRootElement();
		log.info("\t + 4. root : {}", root);
		// + DOM은 node의 계층 구조로 구성되어 있으며, Element는 node의 종류 중 하나이다.
		// + Element는 HTML에서 태그로 적은 노드들을 의미한다.
		// + Element 또한 실제타입을 찍어보니 다른 것을 보아 인터페이스임을 알 수 있다.
		// + 4. root : org.dom4j.tree.DefaultElement@3b220bcb [Element: <response attributes: []/>]
		
		log.info("\t + 4-1. root : {}", root.getName());
		// + 엘리먼트(태그)의 이름을 알려준다.
		// + 4-1. root : response
		
		log.info("\t + 4-2. root Node Type : {}", root.getNodeTypeName());
		// + 어떤 노드 타입인지 알아본다.
		// + 4-2. root Node Type : Element
		
		log.info("\t + 4-3. root text : {}", root.getText());
		
		// ==============================================================
		// 5. DOM의 순회 및 데이터 획득
		// + 찾고자 하는 데이터가 들어가 있는 Element(태그)를 지정한다.
		// + 단, 태그를 찾을 때에는 차근차근 겉에서 안으로 들어가야 한다.
		// ==============================================================
		
		Element body = root.element("body");
		log.info("\t + 5. body : {}",body);
		// + 먼저, 가장 밭에 있는 body 태그에 접근한다.
		
		Element items = body.element("items");
		log.info("\t + 5. items : {}", items);
		// + body 태그 내에 있는 items 태그에 접근한다.
		
		@Cleanup("clear")
		List<Element> item = items.elements("item");
		// + items 태그 밑의 item 엘리먼트(태그)를 리스트에 넣기
		
		for ( Element e : item ) {
			
			// + item 태그에서 필요한 데이터 추출
			Element createDtElement = e.element("createDt");
			Element deathCntElement = e.element("deathCnt");
			Element decideCntElement = e.element("decideCnt");
			Element seqElement = e.element("seq");
			Element stateDtElement = e.element("stateDt");
			Element stateTimeElement = e.element("stateTime");
			Element updateDtElement = e.element("updateDt");
			
			// + String 형태로 변환
			String createDt = createDtElement.getStringValue();
			String deathCnt = deathCntElement.getStringValue();
			String decideCnt = decideCntElement.getStringValue();
			String seq = seqElement.getStringValue();
			String stateDt = stateDtElement.getStringValue();
			String stateTime = stateTimeElement.getStringValue();
			String updateDt = updateDtElement.getStringValue();
			
			// + item에 attr 속성을 넣어서 출력할 수도 있다.
			String attr = e.attributeValue("attr");
			
			log.info("[{}]. createDt : {}, deathCnt : {}, decideCnt : {}, stateDt : {}, stateTime : {}, updateDt : {}, attr : {}",
					seq, createDt, deathCnt, decideCnt, stateDt, stateTime, updateDt, attr );
			
		} // for : 리스트에서 넣은 것을 출력
		
	} // readXML

} // end class

[ 3. XML 문서 parsing하기 XPath engine ( jaxen ) 이용 버전 ] (*****)

 

[ 3 - 1. pom.xml 파일에 디펜던시 추가하기 ]

 

더보기

[ + 코드 보기 ] : jaxen의 이 버전의 경우 취약점이 있으니 조심

      <dependency>
         <groupId>jaxen</groupId>
         <artifactId>jaxen</artifactId>
         <version>1.2.0</version>
      </dependency>

[ 3 - 2. Jaxen 활용하기 ]

 

더보기

[ + 코드 보기 ]

package org.zerock.myapp.dom4j;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;

import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;


@NoArgsConstructor
@Log4j2

@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JaxenTests {
	
	// @Disabled
	@Test
	@Order(1)
	@DisplayName("Step 1. readXML")
	@Timeout(value = 3, unit = TimeUnit.SECONDS)
	void readXML() throws DocumentException {
		
		log.trace("readXML() invoked.");
		
		// ========================================
		// 1. XML SAX Parser 생성 
		// ========================================
		
		SAXReader reader = new SAXReader();
		
		// ====================================================
		// 2. XML 파일 읽어오기 
		// + SAX Parser를 통해 파싱 수행 -> DOM tree 생성
		// ====================================================
		
		reader.setEncoding("utf8");
		// + 최근에는 기본으로 utf8로 지정되어있으나, 혹시 모르니 지정해줘야 한다.
		
		Document doc = reader.read("src/main/resources/Covid19DailyState.xml");
		// + 파일의 경로( = systemId )를 url형태로 작성해 준다.
		
		// ===================================================
		// 3. XPath로 우리가 얻고자 하는 노드들 한번에 선택
		// ===================================================
		
		String xpath = "/response/body/items/item";
		
		@Cleanup("clear")
		List <Node> list = doc.selectNodes(xpath);
		log.info("\t + list size : {}", list.size() );
		
		// ==============================================================
		// 4. DOM의 순회 및 데이터 획득
		// + 찾고자 하는 데이터가 들어가 있는 노드를 지정한다.
		// ==============================================================
		
		for ( Node node : list ) {
			
			Element e = (Element) node;
			// + Element는 Node의 자식 타입이기에 형변환이 가능하다.
			
			// + item 태그에서 필요한 데이터 추출 + String 형태로 변환 ( 메소드 체이닝 )
			String createDt = e.element("createDt").getStringValue();
			String deathCnt = e.element("deathCnt").getStringValue();
			String decideCnt = e.element("decideCnt").getStringValue();
			String seq = e.element("seq").getStringValue();
			String stateDt = e.element("stateDt").getStringValue();
			String stateTime = e.element("stateTime").getStringValue();
			String updateDt = e.element("updateDt").getStringValue();
			
			// + item에 attr 속성을 넣어서 출력할 수도 있다.
			String attr = e.attributeValue("attr");
			
			log.info("[{}]. createDt : {}, deathCnt : {}, decideCnt : {}, stateDt : {}, stateTime : {}, updateDt : {}, attr : {}",
					seq, createDt, deathCnt, decideCnt, stateDt, stateTime, updateDt, attr );
			
		} // for : 리스트에서 넣은 것을 출력
		
	} // readXML

} // end class

 

728x90
댓글
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
최근에 올라온 글
Total
Today
Yesterday
공지사항