본 내용은 혼자서 공부하기 위한 용도로 사용된 것으로 비효율적일 수 있으며 실용적이지 않을 수 있습니다.
주변 정류소 위치를 받아오는 것까지 완료했다. 이제 정류소를 클릭 시 실시간으로 해당 정류소로 들어오는 버스 노선들을 불러와 화면에 보여줄 것이다. 실시간 버스의 경우는 미리 받아올 수 있는 것이 아니기 때문에 실시간으로 API를 받아 xml Parser를 통해 정보를 추출할 것이다.
1. 실시간 버스 정보 가져오기(Xml Parser)
/common/util/setting/BusStopParser.java
@Component("busStopParser")
public class BusStopParser {
public final static String KEY = "키 값";
public List<Map<String,Object>> apiParserNodeRealTime(Map<String,Object> map) throws Exception {
String apiUrl = "http://openapi.tago.go.kr/openapi/service/ArvlInfoInqireService/getSttnAcctoArvlPrearngeInfoList";
URL url = new URL(apiUrl+"?ServiceKey="+KEY+"&nodeId="+map.get("NODEID")+"&cityCode=37030");
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
BufferedInputStream bis = new BufferedInputStream(url.openStream());
xpp.setInput(bis, "utf-8");
String tag = null;
int event_type = xpp.getEventType();
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
Map<String,Object> tempMap = null;
while (event_type != XmlPullParser.END_DOCUMENT) {
if (event_type == XmlPullParser.START_TAG) {
tag = xpp.getName();
if(tag.equals("item")) {
tempMap=new HashMap<String,Object>();
}
} else if (event_type == XmlPullParser.TEXT) {
if(tag.equals("nodeid")){
tempMap.put("NODEID", xpp.getText());
}
else if(tag.equals("routeid")){
tempMap.put("ROUTEID", xpp.getText());
}
else if(tag.equals("routeno")) {
tempMap.put("ROUTENO", xpp.getText());
}
else if(tag.equals("vehicletp")) {
tempMap.put("VEHICLETP", xpp.getText());
}
else if(tag.equals("arrprevstationcnt")) {
tempMap.put("ARRPREV", xpp.getText());
}
else if(tag.equals("arrtime")) {
tempMap.put("ARRTIME", xpp.getText());
}
} else if (event_type == XmlPullParser.END_TAG) {
tag = xpp.getName();
if (tag.equals("item")) {
list.add(tempMap);
}
}
event_type = xpp.next();
}
bis.close();
return list;
}
}
- 전에 살펴봤던 xml parser와 비슷하다. 받아오는 정보로는 정류소ID, 노선 ID, 노선번호, 버스종류, 도착 전 정류장 갯수, 도착 시간을 받아와 list에 저장 후 리턴한다.
2. Controller
GCBusController.java
@RequestMapping(value="/nodeRealTime.do")
public @ResponseBody ModelAndView nodeRealTime(@RequestBody Map<String,Object> map) throws Exception{
map.put("list", busStopParser.apiParserNodeRealTime(map));
return new ModelAndView("jsonView", map);
}
- 전에 살펴봤던 것 처럼 @ResponseBody, @RequestBody 형식으로 이루어져 있고 위에서 파싱한 실시간 버스 정보를 받아와 json 형식으로 변환 후 뷰단으로 리턴한다.
3. JSP
해당 코드를 추가한다.
node_find.jsp
function fn_clickNode(obj){
setMarkers(null);
//if(customOverlay!=null){
// customOverlay.setMap(null);
//}
if($("a[name^='node']").hasClass("selected")){
$("a[name^='node']").removeClass("selected");
fn_clickSearchButton();
}else{
$("a[name^='node']").addClass("selected");
fn_nodeRealTime(obj);
}
}
function fn_nodeRealTime(obj){
//버스 노선 페이지에서 검색된 경로의 정류장의 정보보기의 기능 활성화의 경우를 위한 변수들 초기화
if($("#nodeidVal").val()!=null&&!($("#nodeidVal").hasClass("used"))){
var str = "<a href='#this' nodeid='"+$("#nodeidVal").val()+"' lat='"+$("#latVal").val()+"' lng='"+$("#lngVal").val()+"' name='node1' id='node1' class='result sc_node_result'>"+$("#nodenameVal").val()+"</a>";
$("#resultBox").append(str);
obj=$("#node1"); $(obj).addClass("selected");
$("#nodeidVal").addClass("used");
}
//지도 중심을 변경합니다.
map.setCenter(new daum.maps.LatLng(obj.attr("lat"),obj.attr("lng")));
//선택한 정류장의 오버레이를 활성화합니다.
//fn_setOverlay(obj);
var divStr="<div id='routeBox' class='result'><div id='pageDiv'></div></div>";
obj.siblings().remove();
obj.parent().append(divStr);
//선택한 정류장의 위치에 마커를 표시한다.
fn_nodeMarkerMaker(obj); /*
이 부분에서 정류장 ID를 서버로 보내주고 서버에서는 OPEN API를 통해 정류장 실시간 도착 노선 정보를 가져와 ajax로 리턴해준다.
보내는 데이터 : nodeID
받는 데이터 : 정류장 실시간 도착 정보
*/
$.ajax({
dataType:"json",
type:"POST",
contentType:"application/json",
url:"/gcbus/nodeRealTime.do",
data:JSON.stringify({NODEID:obj.attr("nodeid")}),
success:function(result){
for(var i=0;i<result["list"].length;i++){
var map=result["list"][i];
var arrtime= Math.floor(map["ARRTIME"]/60);
var str = "<a href='#this' routeno='"+map["ROUTENO"]+"' routeid='"+map["ROUTEID"]+"' name='route"+i+"' id='route"+i+"' class='result sc_real_route_result'>"+map["ROUTENO"]
+"("+map["VEHICLETP"]+")<p>"+map["ARRPREV"]+"정류장 전("+arrtime+"분)</p></a>"; $("#routeBox").append(str);
} $("#routeBox").css("height", 52*result["list"].length);
$("#routeBox").append("<a href='#this' id='busList_Btn' class='btn' >모든 버스 노선 보기</a>");
$("a[name^=route]").on("click",function(e){
e.preventDefault();
//fn_routeInfo($(this));
});
$("#busList_Btn").on("click",function(e){
e.preventDefault();
//fn_nodeToRoute(obj);
});
},
error:function(){
alert("error");
}
})
}
- fn_clickNode() 함수의 경우 자바스크립트로 해당 Div가 가진 클래스를 확인하여 정류소를 처음 클릭하면 실시간 버스 정보가 출력되지만 다시 클릭할 시 다시 정류소 리스트 화면으로 돌아 가기 위한 함수이다. 다음 fn_nodeReadlTime()는 controller에서 보낸 실시간 버스 정보를 받아오기 위한 함수로 먼저 버스 노선 페이지에서 해당 페이지로 전환되었을 때 정류장 정보를 할당해주는 부분이므로 지금은 넘어가도록 하고 나중에 다시 살펴보길 바란다(20~25).
- 27~34라인
검색 버튼을 누를 경우 지도의 중앙을 해당 정류소로 먼저 설정해준 뒤 29라인 부분은 나중에 사용하게 될 예정이다. 현재는 주석처리하고 나중에 주석을 해제할 것이다. 다음 노선을 나타낼 노선박스를 작성한 후 선택한 정류장 위치에 마커로 표시 한다.
-39~67라인
nodeRealTime.do로 정류장ID 값을 보낸다. 그리고 정류장에 실시간으로 도착하는 버스노선에 대한 정보를 받아와 적당히 이쁘게 꾸미고(49~51) 출력한다. 그리고 미리 버스노선 버튼에 대한 클릭 이벤트를 만들어놓았지만 다음 포스팅에서 다룰 것이다.
4. 테스트
여기까지 따라왔다면 밑과 같은 결과값을 낼 수 있을 것이다.
- 위 버튼을 클릭 할 시
- 다음과 같은 화면이 나타난다면 오늘의 과정도 잘 따라왔다는 것을 확인 할 수 있다.(모든 버스 노선 보기, 노선에 대한 클릭의 클릭 이벤트는 다음 포스팅에서 다루겠다.)