관심분야/모바일서버

제주버스OpenApi 적용방식(1)

을량 2019. 7. 16. 11:53

제주지니 버스 OpenApi 업데이트 요청이 있어서 수정보안도 하고 해당 OpenApi 적용방식에 대해 포스팅 하려고 합니다.

제주도에서 가장 신뢰할수 있는 버스OpenApi 확인결과 제주도청에서 제공하는 제주버스 OpenApi를 적용하기로 하였습니다.

 

1) OpenApi  구조

   1.www.data.go.kr(공공데이타포탈)에서 회원가입 

   2.적용하여고 하는 OpenApi검색

   3.선정후 신청->승인후 적용(보통 자동승인)

   4.인증키를 OpenApi 호출시 파라미터로 세팅

   5.데이터 포맷 XML  

   6.호출API 문서를 기준으로 개발

 

2) 적용  OpenApi  항목

   1.전체 노선 리스트 정보

   2.노선 상세정보

   3.노선 버스 위치 목록

   4.전체 정류장 리스트 정보

   5.정류장 버스 도착정보

   6.전체 버스 리스트 정보

   7.정류장 경유 노선 리스트 정보

 

적용예)

맛집 위도경도를 기준으로 버스정류장을 표시함
맛집주면 정류장확인 빨간핀으로 표시된 곳이 정류장
버스정류장 클릭시 탈수있는 버스와 실시간 교통정보 확인가능
버스클릭시 해당버스의 실시간 정보 확인가능 저상인경우 저상표시

3) 온라인성과 배치성 호출 구분

- 온라인 Open Api 호출의 개발자 편의성을 위해 Utility 개발

- 배치성 Open Api 호출하여 DB에 변경분과 기본데이타를 적재

 

3-1) OpenApi 데이타포맷 XML

- 응답포맷이 xml이기 때문에 공통함수로 개발자들이 편하게 사용할수 있도록 메소드 개발하여 적용

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import com.ssf.data.SBox;
import com.ssf.exception.SSysException;
import com.ssf.log.SErrorLog;

public class XmlUtil
{

   /**
    * 1. 개요 : URL로 얻어오는 xml정보를 리스트 SBox 로 리턴한다.
    * 2. 처리내용 :url 필수, targetRoot 대상루트지정 필수 , tagValueList 대상루트에서 읽어와야할 대상정보리스트 필수 
    * @Method Name :getUrlXmlIfBySBox
    * @param url
    * @param targetRoot
    * @param tagValueList
    * @return
    * @throws SSysException
    */
   public static List<SBox> getUrlXmlIfBySBox(String url, String targetRoot, List<String> tagValueList)
         throws SSysException
   {
      return getXmlIfBySBox(url, targetRoot, tagValueList);
   }

   /**
    * 1. 개요 : 파일객체로 얻어오는 xml정보를 리스트 SBox 로 리턴한다.
    * 2. 처리내용 :url 필수, targetRoot 대상루트지정 필수 , tagValueList 대상루트에서 읽어와야할 대상정보리스트 필수 
    * @Method Name :getUrlXmlIfBySBox
    * @param url
    * @param targetRoot
    * @param tagValueList
    * @return
    * @throws SSysException
    */
   public static List<SBox> getFileXmlIfBySBox(String filePh, String targetRoot, List<String> tagValueList)
         throws SSysException
   {
      if (StringUtil.isEmpty(filePh))
      {
         throw new SSysException("COMXMLCD001");
      }
      
      File file = new File(filePh);
      
      if(!file.exists())
      {
         throw new SSysException("COMXMLCD001");
      }
            
      return getXmlIfBySBox(file, targetRoot, tagValueList);
   }

   private static String getTagValue(String sTag, Element eElement)
   {
      NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();

      Node nValue = (Node) nlList.item(0);

      return nValue.getNodeValue();
   }

   private static List<SBox> getXmlIfBySBox(Object targetIf, String targetRoot, List<String> tagValueList)
         throws SSysException
   {
      List<SBox> rtnList = new ArrayList<SBox>();
      try
      {
         if (StringUtil.isEmpty(targetIf))
         {
            throw new SSysException("COMXMLCD001");
         }

         if (StringUtil.isEmpty(targetRoot))
         {
            throw new SSysException("COMXMLCD002", targetRoot);
         }

         if (StringUtil.isEmpty(tagValueList))
         {
            throw new SSysException("COMXMLCD003");
         }
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
         dbFactory.setValidating(false);
         dBuilder.setErrorHandler(new XmlErrorHandler());
      
         Document doc = null;
         if (targetIf.getClass() == String.class)
         {
            try {
               doc = dBuilder.parse(targetIf.toString());
            } catch (Exception e) {
               dbFactory =null;
               dBuilder = null;
               return rtnList;
            }
            
         } else if (targetIf.getClass() == File.class)
         {
            doc = dBuilder.parse((File) targetIf);
         } else
         {
            throw new SSysException("COMXMLCD001");
         }

         doc.getDocumentElement().normalize();

         NodeList nList = doc.getElementsByTagName(targetRoot);

         for (int temp = 0; temp < nList.getLength(); temp++)
         {

            Node nNode = nList.item(temp);
            if (nNode.getNodeType() == Node.ELEMENT_NODE)
            {

               Element eElement = (Element) nNode;
               SBox sbox = new SBox();
               for (String string : tagValueList)
               {
                  //SDebugLog.println(getTagValue(string, eElement));
                  sbox.setString(string, getTagValue(string, eElement));
               }
               rtnList.add(sbox);
            }
         }
      } catch (Exception e)
      {
         SErrorLog.fullStackTrace(e);
         throw new SSysException("COMXMLCD004");
      }

      return rtnList;
   }   
}
class XmlErrorHandler implements ErrorHandler { 
   
   //well-formed 오류가 발생했을 때
   public void fatalError(SAXParseException exception) throws SAXException{
      SErrorLog.println(exception.getMessage());
   }

   //validating 오류가 발생했을 때
   public void error(SAXParseException exception) throws SAXException{
	   SErrorLog.println(exception.getMessage());
   }

   //경고성 오류가 발생했을 때(파서마다 오류를 발생시키는 경우가 다르다)
   public void warning(SAXParseException exception) throws SAXException{
	   SErrorLog.println(exception.getMessage());
   }

} 

 

3-2) 온라인 개발  

- 노선 버스 위치 목록/정류장 버스 도착정보는 온라인으로 실시간 호출되어야 함

- 공통 개발이 먼저 선행

	/**
	 * Desc : 노선 버스 위치 목록 (노선 실시간 버스 위치)
	 * 
	 * @param param
	 * @return
	 * @throws SSysException
	 * @throws Exception.
	 */
	public SBox getLocationRouIdByBus(SBox param) throws SBizException, SSysException {

		if (!param.containsKey("ROU_ID")) {
			throw new SBizException("COMSSFCD130", "버스노선 ID");
		}

		if (StringUtil.isEmpty(param.getString("ROU_ID"))) {
			throw new SBizException("COMSSFCD130", "버스노선 ID");
		}

		SBox busBox = new SBox();

		String urlStr = "http://busopen.jeju.go.kr/OpenAPI/service/bis/BusPosition?serviceKey=인증키&route="
				+ param.getString("ROU_ID");

		List<String> list = new ArrayList<String>();
		list.add("arrvStationId");
		list.add("lowPlateTp");
		list.add("plateNo");

		List<SBox> rtnlist = new ArrayList<SBox>();
		try {
			rtnlist = XmlUtil.getUrlXmlIfBySBox(urlStr, "item", list);
		}
		catch(Exception e1) {
			
		}
		
		List<Map<String, Object>> datalist = new ArrayList<Map<String, Object>>();

		for (SBox data : rtnlist) {
			Map<String, Object> busMap = new HashMap<String, Object>();
			busMap.put("BTP_N", data.getString("arrvStationId"));
			busMap.put("BUS_LOW_F", data.getString("lowPlateTp"));
			busMap.put("BUS_NLT_NM", data.getString("plateNo"));
			datalist.add(busMap);
		}

		busBox.put("BUS_CNT", datalist.size());
		busBox.put("BUS_IF", datalist);

		return busBox;
	}
	/**
	 * Desc : 정류장 버스 도착정보
	 * 
	 * @param param
	 * @return
	 * @throws SSysException
	 * @throws Exception.
	 */
	public SBox getArriveBusByBtp(SBox param) throws SBizException, SSysException {
		if (!param.containsKey("BTP_N")) {
			throw new SBizException("COMSSFCD130", "정류장 ID");
		}

		if (StringUtil.isEmpty(param.getString("BTP_N"))) {
			throw new SBizException("COMSSFCD130", "정류장 ID");
		}

		SBox busBox = new SBox();

		String urlStr = "http://busopen.jeju.go.kr/OpenAPI/service/bis/BusArrives?serviceKey=인증키&station="
				+ param.getString("BTP_N");

		List<String> list = new ArrayList<String>();
		list.add("arrvVhId");
		list.add("calcDate");
		list.add("leftStation");
		list.add("predictTravTm");
		list.add("routeId");
		list.add("stationOrd");

		List<SBox> rtnlist = new ArrayList<SBox>();
		rtnlist = XmlUtil.getUrlXmlIfBySBox(urlStr, "item", list);

		List<Map<String, Object>> datalist = new ArrayList<Map<String, Object>>();

		for (SBox data : rtnlist) {
			Map<String, Object> busMap = new HashMap<String, Object>();
			busMap.put("LFT_BAS_TM", data.getString("predictTravTm"));
			busMap.put("VH_ID", data.getString("arrvVhId"));
			busMap.put("LFT_BTP_CNT", data.getString("leftStation"));
			busMap.put("LFT_BTP_TM", data.getString("predictTravTm"));
			busMap.put("ROU_ID", data.getString("routeId"));
			busMap.put("BTP_SN", data.getString("stationOrd"));
			datalist.add(busMap);
		}

		busBox.put("BUS_CNT", datalist.size());
		busBox.put("BUS_IF", datalist);

		return busBox;
	}

2편에서 만나요