본문 바로가기

Java/Source_book

[ 2010.07.19 - 20 AJAX 실습 및 정리 ] – Word 버전

[ 2010.07.19 AJAX ]

AJAX(Asynchronous Javascript And XML)

(= Client와 Server 사이에 비동기적으로 JavaScript와 XML을 이용하여 Data를 교환하는 프로그래밍 기법.)

우측 그림과 같이 비동기적으로 통신을 하기 때문에, Client가 Server에게 보낸 요청에 대한 응답이 오지 않아도, Client는 계속 작업을 수행할 수 있다.

 

구현 Procedure

  • XMLHttpRequest 객체 설정

    Ajax에서 비동기 통신을 위한 핵심 JavaScript 객체로서, Web Browser에 따라 사용법이 다르다.

     

function createXMLHttpRequest(){

if(window.ActiveXObject){//IE 계열 Web Browser

xhr=new ActiveXObject("Microsoft.XMLHTTP");

}else{//IE 계열 외의 Web Browser

xhr=new XMLHttpRequest();

}

}

 

  • Server에 Request 정보 전달

    XMLHttpRequest 객체의 함수 { open( ) & send( ) } 를 이용한다.

     

    open( "POST | GET" , "요청 정보를 보낼 URL", "true | false" );

     

    true는 동기식 전송방식, false는 비동기식 전송방식.

     

    send( )

    Argument로 POST 방식일 경우 Query String을, GET 방식일 경우 null 을 지정한다.

  • Server에서 넘어온 Response Data 처리하기.

    일반적으로 CallBack의 의미는 자동으로 호출되는 Method를 의미하며, 서버에서 넘어온 응답 정보를 기반으로 하여 개발자가 처리해야할 Logic을 구현한다.

    CallBack 메소드를 사용하기 위해서는

     

    XMLHttpRequest 객체.onreadystatechange= CallBack 함수;

     

    로 우선 등록하여야 한다.

     

    Server에서 넘어온 응답 Data는 크게 2종류로 나눌 수 있는데

    Text Type일 경우 XMLHttpRequest.responseText;

    Xml Type일 경우 XMLHttpRequest.responseXML;

    로 받아올 수 있다.

 

[ 실습 1 ]

프로젝트 : [Dynamic Web Project] ajax_basic_1

구조 : greeting.html & register.html & AjaxSErvlet.java로 이루어진다.

응답을 처리해줄 Servlet : controller.AjaxServlet (Mapping : /controller)

 

greeting.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>2010.07.19 Ajax 시작</title>

<script>

var xhr;//XmlHttpRequest 객체를 할당할 전역변수.

//XmlHttpRequest 객체 생성 function

function createXMLHttpRequest(){

if(window.ActiveXObject){//IE 계열 Web Browser

xhr=new ActiveXObject("Microsoft.XMLHTTP");

}else{//IE 계열 Web Browser

xhr=new XMLHttpRequest();

}

}

 

//Click Event처리 ---> 서버(AjaxServlet) 비동기적으로 인사말요청

function getGreeting(){

//비동기적 요청

/*

1. XMLHttpRequest 객체 생성

2. XMLHttpRequest 객체에 call back () 등록(=응답이 왔을 처리할 함수)

3. XMLHttpRequest open() 호출하여 요청할 CGI 등록.

4. XMLHttpRequest send() 호출하여 서버에 요청.

*/

 

 

createXMLHttpRequest();

xhr.onreadystatechange=callback;//readyStateChange 이벤트 핸들러

xhr.open("GET","controller?command=greeting",false);

xhr.send(null); //get방식에선 null 넘긴다.

}

 

function getHello(){

 

createXMLHttpRequest();

//xhr.onreadystatechange=callback; //경고창 <body>부분에 정보출력 CallBack

xhr.onreadystatechange=getdata;//innerHTML 실습

 

var language=document.form1.lang.value;

xhr.open("get","controller?command=get_hello&lang="+language,false);

xhr.send(null);

 

}

//xhr readyState 바뀔 때마다 호출되는 Method

function callback(){

//alert(xhr.readystate);

if(xhr.readyState==4){//서버의 응답이 완료되었다면

if(xhr.status==200){//정상적인 응답이라면

var responseData=xhr.responseText;//서버가 보낸 값을 문자열로 Return

//경고창에 출력

alert("응답 결과 : "+ responseData);

//화면에 출력

var res=document.createTextNode(responseData);

document.body.appendChild(res);

}

}

}

 

function getdata(){

if(xhr.readystate==4){

if(xhr.status==200){

//서버에서 보내온 값을 'resTxt' 저장

var resTxt="<font color=red>"+ xhr.responseText +"</font>";

document.getElementById("res").innerHTML=resTxt;

}

}

}

</script>

</head>

<body>

<input type="button" value="인사말요청" onClick="getGreeting()"/>

<hr/>

Server에서 보내온 : <span id="res"></span><!-- innerHTML 실습 -->

<form name="form1" >

조회언어 : <input type="text" name="lang" /> 한국어 : kor, 영어 : eng<br/>

<input type="button" onClick="getHello()" value="요청"/>

</form>

</body>

</html>

 

AjaxServlet.java

package controller;

 

//import 정보 생략

 

public class AjaxServlet extends HttpServlet {

 

protected void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doPost(request,response);

}

 

protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

 

request.setCharacterEncoding("euc-kr");

String command=request.getParameter("command");

if(command.equals("greeting")){

getGreeting(request,response);

}else if(command.equals("get_hello")){

getHello(request,response);

}else if(command.equals("id_dup_check")){

idDupCheck(request,response);

}

}

/*

* Client가 command=greeting으로 요청한 것을 처리하는 controller 메소드.

* '안녕하세요'를 응답한다.

*/

public void getGreeting(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException{

response.setContentType("text/html;charset=euc-kr");

 

//Header의 cache설정

//Cache 비활성화, Ajax 실습을 위해선, Web Brwoser에 따라서 실습이 안될 수 있으므로 캐쉬설정을 비활성화시킨다.

response.setHeader("Cache-Control", "no-cache");

PrintWriter out=response.getWriter();

out.println("안녕하세요");

out.close();

}

public void getHello(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException{

 

String lang=request.getParameter("lang");

 

//kor이면 한글로, eng이면 영어로 인사말 return

String greeting=null;

if(lang.equalsIgnoreCase("kor")){

greeting="안녕하세요?!";

}else if(lang.equalsIgnoreCase("eng")){

greeting="Hello, How r u?!";

}

response.setContentType("text/html;charset=euc-kr");

response.setHeader("Cache-Control", "no-cache");

PrintWriter out=response.getWriter();

out.println(greeting);

out.close();

}

public void idDupCheck(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException{

 

//ID Duplication Check

ArrayList<String> idList=new ArrayList<String>();

idList.add("1111");

idList.add("2222");

idList.add("3333"); //DB에 등록된 ID목록

 

//Client에서 넘어온 ID값 받기

String id=request.getParameter("id");

String message=id+"는 사용할 수 있는 아이디 입니다.";

for(String obj: idList){

if(id.equals(obj)){

message=id+"는 이미 등록된 아이디 입니다.";

}

}

 

//Response

response.setContentType("text/html;charset=euc-kr");

response.setHeader("Cache-Control", "no-cache");

PrintWriter out=response.getWriter();

out.println(message);

out.close();

}

} 

 

register.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>2010.07.19 AJAX</title>

</head>

<script>

var xhr;

function idDupCheck(){

//xhr생성

if(window.ActiveObject){

xhr=new ActiveXObject("Microsoft.XMLHTTP");

}else{

xhr=new XMLHttpRequest();

}

 

//입력한 ID 읽기 기본검사

var id=document.register_form.id.value;

var msg=document.getElementById("message");

if(id.length<3){

//alert("ID 최소 3글자 이상 입력해주세요");

msg.innerHTML="ID 6글자 이상 입력하세요";

return;

}

 

//CallBack 함수 등록 open(),send()

xhr.onreadystatechange=getData;

xhr.open("GET","controller?command=id_dup_check&id="+id,false);

xhr.send(null);

}

function getData(){//CallBack 함수

if(xhr.readyState==4){

if(xhr.status==200){

var resTxt=xhr.responseText;

//alert(resTxt);

var msg=document.getElementById("message");

msg.innerHTML=resTxt;

 

}

}

}

</script>

<body>

<b>Register_Form</b><hr/>

<form name="register_form">

<!-- 등록 버튼을 누를 이벤트 실행 -->

<!-- ID:<input type="text" name="id"/><font size"2" color="red"><span id="message"></span></font><br/> -->

 

//위는 버튼을 눌렀을 server, 밑은 Keyboard 눌릴 마다 Server 통신

 

<!-- Keyboard에서 사용자의 입력값들이 입력될 마다! -->

ID:<input type="text" name="id" onKeyUp="idDupCheck()"/><font size"2" color="red"><span id="message"></span></font><br/>

기타입력폼

<input type="button" value="등록" onClick="idDupCheck()"/>

 

</form>

</body>

</html>

 

실습결과 확인 –greeting.html

< 기본 화면 >

 

 

실습결과 확인 –register.html

<기본 화면>

 

 

[ 2010.07.19 AJAX ]

서버단에서 select 태그 생성

ajaxServlet

protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

 

request.setCharacterEncoding("euc-kr");

String command=request.getParameter("command");

if(command.equals("greeting")){

getGreeting(request,response);

}else if(command.equals("get_hello")){

getHello(request,response);

}else if(command.equals("id_dup_check")){//ID 중복 체크를 위함. -register.html에서 넘어옴.

//중복체크

idDupCheck(request,response);

}else if(command.equals("get_category")){//1 카테고리 선택시 이에 따른 2 카테고리 나옴

getSecondCategory(request,response);

}

}

 

 

 

public void getSecondCategory(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException{

//대분류에 대한 소분류를 select return

String firstCatgory=request.getParameter("firstCategory");

response.setContentType("text/html;charset=euc-kr");//한글처리

response.setHeader("Cache-Control", "no-cache");//캐쉬 비활성화

PrintWriter out=response.getWriter();

 

//응답메세지를 저장할 StringBuffer생성

StringBuffer buffer=new StringBuffer(200);

buffer.append("<select name='secondCategory'>");

buffer.append("<option value='default'>소분류</option>");

 

//DB 부터 소분류 항목을 가져온다.

if(firstCatgory.equals("computer")){

String[] sCategory={"노트북","데스크탑","모니터","주변기기"};

for(String str: sCategory){

buffer.append("<option>"+str+"</option>");

}

}else if(firstCatgory.equals("electronic")){

String[] sCategory={"TV","냉장고","DVD플레이어","전자렌지","세탁기"};

for(String str: sCategory){

buffer.append("<option>"+str+"</option>");

}

}else if(firstCatgory.equals("cloth")){

String[] sCategory={"남성정장","여성정장","아동복","스포츠의류","케쥬얼","잡화"};

for(String str: sCategory){

buffer.append("<option>"+str+"</option>");

}

}

buffer.append("</select>");

out.println(buffer.toString());

out.close();

}

Category.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>2010.07.20</title>

<script>

var xhr;

 

function getSeondCategory(){

//XMLHttpRequest 생성

if(window.ActiveXObject){

xhr=new ActiveXObject("Microsoft.XMLHTTP");

}else{

xhr=new XMLHttpRequest();

}

 

var fCategory=document.getElementById("first_category");

var fCategoryValue=fCategory.options[fCategory.selectedIndex].value;

 

if(fCategoryValue=="default"){

return;

}

var url="controller?command=get_category&firstCategory="+fCategoryValue;

 

//XMLHttpRequest 객체 xhr CallBack함수 등록

xhr.onreadystatechange=getSelect;

 

//xhr open & send

xhr.open("GET",url,false);

 

xhr.send(null);

}

//xhr readyState 상태가 바뀔때 마다 호출된다. CallBack 함수

function getSelect(){

//정상적응답이 완료되면 처리하도록 설정

if(xhr.readyState==4){

if(xhr.status==200){

//응답 값을 조회

var resTxt=xhr.responseText;

alert(resTxt);

var span=document.getElementById("second_category_span");

span.innerHTML=resTxt;

}

}

}

 

</script>

</head>

<body>

상품 카테고리<br/>

<select name="first_category" id="first_category" onChange="getSeondCategory()">

<option value="default">대분류</option>

<option value="computer">COMPUTER</option>

<option value="electronic">ELECTRONIC</option>

<option value="cloth">CLOTH</option>

</select>

<span id="second_category_span"></span>

</body>

</html>

 

 

이번에는 클라이언트 단에서 select 태그를 생성하는 방법

이를 위해

Ajaxservlet

protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

 

request.setCharacterEncoding("euc-kr");

String command=request.getParameter("command");

if(command.equals("greeting")){

getGreeting(request,response);

}else if(command.equals("get_hello")){

getHello(request,response);

}else if(command.equals("id_dup_check")){//ID 중복 체크를 위함. -register.html에서 넘어옴.

//중복체크

idDupCheck(request,response);

}else if(command.equals("get_category")){//1 카테고리 선택시 이에 따른 2 카테고리 나옴

//getSecondCategory(request,response);

getSecondCategory2(request,response);

}

}

 

function getSelect2(){

if(xhr.readyState==4){

if(xhr.status==200){

//select 노드를 생성한다.

var sel=document.createElement("select");

//응답 데이터 조회 - eval() : 문자열을 javascript 해당 형태로 변환 (여기선 배열로 변환.)

var txt=eval(xhr.responseText);

 

for(i=0; i<txt.length; i++){

sel[i]=new Option(txt[i],txt[i]);

}

//Option노드는 createElement() 생성하지않고

//new Option(value,text); 생성

//select[idx]=option객체; 구문으로 select 붙인다.

var span=document.getElementById("second_category_span");

//자식노드가 있으면 삭제 추가.

while(span.childNodes[0]){

span.removeChild(span.childNodes[0]);

}

span.appendChild(sel);

}

}

}

Category.html

//XMLHttpRequest 객체 xhr CallBack함수 등록

//xhr.onreadystatechange=getSelect;

xhr.onreadystatechange=getSelect2;

 

 

function getSelect2(){

if(xhr.readyState==4){

if(xhr.status==200){

//select 노드를 생성한다.

var sel=document.createElement("select");

//응답 데이터 조회 - eval() : 문자열을 배열로 변환.

var txt=eval(xhr.responseText);

 

for(i=0; i<txt.length; i++){

sel[i]=new Option(txt[i],txt[i]);

}

//Option노드는 createElement() 생성하지않고

//new Option(value,text); 생성

//select[idx]=option객체; 구문으로 select 붙인다.

var span=document.getElementById("second_category_span");

span.appendChild(sel);

}

}

}

 

 

[ 실습3 ] 지하철노선도를 위와 같이 실시간적으로 DropDownList로 생성하라.

Dynamic Web Project名 : ajaxsubway

Flow Chart 

  1. index.html은 우선 controller에 QueryString command=all_line 을 가지고 넘어간다.
  1. Controller는 이에 해당하는 SelectAllLine( )이 있는지 확인하고 조건에 맞는 Method를 실행한다.
  1. SelctAllLine( )는 DB로부터 모든 '지하철 호선' 정보를 가져와 그 값을 subway.jsp로 응답한다.
  1. 사용자가 다시 특정 호선을 선택하면 Ajax를 통한 비동기처리방식으로 command=get_station 값을 controller에 넘겨준다.
  1. 이를 기반으로 DB에서 그 호선의 '지하철 역(station)'들을 다시 subway.jsp로 보내준다.

 

우선 실습을 위해 DB에서 해당 Table 및 실습을 위한 예제 Data들을 Insert 한다.

DB 관련 SQL

create table subway(

no number primary key,

line varchar2(2) not null,

station varchar2(40) not null

);

 

drop subway_seq;

--sequence

create sequence subway_seq

 

insert into subway values (subway_seq.NEXTVAL, '1', '수원');

insert into subway values (subway_seq.NEXTVAL, '1', '화서');

insert into subway values (subway_seq.NEXTVAL, '1', '성균관대');

insert into subway values (subway_seq.NEXTVAL, '1', '의왕');

insert into subway values (subway_seq.NEXTVAL, '1', '군포');

insert into subway values (subway_seq.NEXTVAL, '1', '부곡');

insert into subway values (subway_seq.NEXTVAL, '1', '금정');

insert into subway values (subway_seq.NEXTVAL, '1', '명학');

insert into subway values (subway_seq.NEXTVAL, '1', '안양');

insert into subway values (subway_seq.NEXTVAL, '1', '관악');

insert into subway values (subway_seq.NEXTVAL, '1', '석수');

insert into subway values (subway_seq.NEXTVAL, '1', '구로');

 

insert into subway values (subway_seq.NEXTVAL, '2', '신도림');

insert into subway values (subway_seq.NEXTVAL, '2', '신대방');

insert into subway values (subway_seq.NEXTVAL, '2', '신림');

insert into subway values (subway_seq.NEXTVAL, '2', '봉천');

insert into subway values (subway_seq.NEXTVAL, '2', '서울대입구');

insert into subway values (subway_seq.NEXTVAL, '2', '낙성대');

insert into subway values (subway_seq.NEXTVAL, '2', '사당');

insert into subway values (subway_seq.NEXTVAL, '2', '방배');

insert into subway values (subway_seq.NEXTVAL, '2', '서초');

insert into subway values (subway_seq.NEXTVAL, '2', '교대');

insert into subway values (subway_seq.NEXTVAL, '2', '강남');

 

insert into subway values (subway_seq.NEXTVAL, '3', '수서');

insert into subway values (subway_seq.NEXTVAL, '3', '일원');

insert into subway values (subway_seq.NEXTVAL, '3', '대청');

insert into subway values (subway_seq.NEXTVAL, '3', '학여울');

insert into subway values (subway_seq.NEXTVAL, '3', '대치');

insert into subway values (subway_seq.NEXTVAL, '3', '도곡');

insert into subway values (subway_seq.NEXTVAL, '3', '매봉');

insert into subway values (subway_seq.NEXTVAL, '3', '양재');

insert into subway values (subway_seq.NEXTVAL, '3', '교대');

insert into subway values (subway_seq.NEXTVAL, '3', '고속터미널');

 

insert into subway values (subway_seq.NEXTVAL, '4', '사당');

insert into subway values (subway_seq.NEXTVAL, '4', '총신대입구');

insert into subway values (subway_seq.NEXTVAL, '4', '동작');

insert into subway values (subway_seq.NEXTVAL, '4', '이촌');

insert into subway values (subway_seq.NEXTVAL, '4', '신용산');

insert into subway values (subway_seq.NEXTVAL, '4', '삼각지');

insert into subway values (subway_seq.NEXTVAL, '4', '숙대입구');

insert into subway values (subway_seq.NEXTVAL, '4', '서울역');

insert into subway values (subway_seq.NEXTVAL, '4', '회현');

insert into subway values (subway_seq.NEXTVAL, '4', '명동');

 

 

insert into subway values (subway_seq.NEXTVAL, '5', '마천');

insert into subway values (subway_seq.NEXTVAL, '5', '거여');

insert into subway values (subway_seq.NEXTVAL, '5', '오금');

insert into subway values (subway_seq.NEXTVAL, '5', '방이');

insert into subway values (subway_seq.NEXTVAL, '5', '올림픽공원');

insert into subway values (subway_seq.NEXTVAL, '5', '둔촌동');

insert into subway values (subway_seq.NEXTVAL, '5', '강동');

insert into subway values (subway_seq.NEXTVAL, '5', '천호');

insert into subway values (subway_seq.NEXTVAL, '5', '광나루');

insert into subway values (subway_seq.NEXTVAL, '5', '아차산');

 

insert into subway values (subway_seq.NEXTVAL, '6', '봉화산');

insert into subway values (subway_seq.NEXTVAL, '6', '화랑대');

insert into subway values (subway_seq.NEXTVAL, '6', '태릉');

insert into subway values (subway_seq.NEXTVAL, '6', '석계');

insert into subway values (subway_seq.NEXTVAL, '6', '월곡');

insert into subway values (subway_seq.NEXTVAL, '6', '고려대');

insert into subway values (subway_seq.NEXTVAL, '6', '안암');

insert into subway values (subway_seq.NEXTVAL, '6', '보문');

insert into subway values (subway_seq.NEXTVAL, '6', '신당');

insert into subway values (subway_seq.NEXTVAL, '6', '청구');

 

insert into subway values (subway_seq.NEXTVAL, '7', '반포');

insert into subway values (subway_seq.NEXTVAL, '7', '논현');

insert into subway values (subway_seq.NEXTVAL, '7', '학동');

insert into subway values (subway_seq.NEXTVAL, '7', '강남구청');

insert into subway values (subway_seq.NEXTVAL, '7', '청담');

insert into subway values (subway_seq.NEXTVAL, '7', '뚝섬유원지');

insert into subway values (subway_seq.NEXTVAL, '7', '건대입구');

insert into subway values (subway_seq.NEXTVAL, '7', '군자');

insert into subway values (subway_seq.NEXTVAL, '7', '중곡');

insert into subway values (subway_seq.NEXTVAL, '7', '용마산');

 

insert into subway values (subway_seq.NEXTVAL, '8', '모란');

insert into subway values (subway_seq.NEXTVAL, '8', '수진');

insert into subway values (subway_seq.NEXTVAL, '8', '신흥');

insert into subway values (subway_seq.NEXTVAL, '8', '산성');

insert into subway values (subway_seq.NEXTVAL, '8', '복정');

insert into subway values (subway_seq.NEXTVAL, '8', '가락시장');

insert into subway values (subway_seq.NEXTVAL, '8', '송파');

insert into subway values (subway_seq.NEXTVAL, '8', '석촌');

insert into subway values (subway_seq.NEXTVAL, '8', '잠실');

insert into subway values (subway_seq.NEXTVAL, '8', '몽촌토성');

 

우선 index.html을 작성한다.

Index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>Insert title here</title>

</head>

<body>

<a href="subwayController?command=all_line">subway.jsp 이동</a>

</body>

</html>

위와 같이 코드는 매우 단순하다. 그저 DAO에 직접적으로 접근하지 않고, 요청이 Controller를 거쳐가도록 Link를 걸어준 것이다.

 

이제 SubwayController.java 파일을 작성한다.

SubwayController.java

package action;

 

//import 정보생략

 

public class SubwayController extends HttpServlet {

SubwayDAO dao;

 

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {

doPost(request,response);

}

 

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {

request.setCharacterEncoding("euc-kr");//한글화 처리

String command=request.getParameter("command");

 

if(command.equals("all_line")){

SelectAllLine(request,response);//지하철 호선 가져오기

}else if(command.equals("get_station")){

SelectStation(request,response);//사용자가 선택한 호선의 역(station) 정보 가져오기

}

}

 

public List SelectAllLine(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{

 

dao=SubwayDAO.getInstance(); //SubwayDAO의 객체를 받아 온다. (Singleton 처리)

try {

List list=dao.SelectAllLine();//Query 실행 값을 List Type 변수 list에 저장.

 

request.setAttribute("list", list); //subway.jsp로 넘기기 위해 request scope에 "list"라는 이름으로 list 저장

 

RequestDispatcher rdp=request.getRequestDispatcher("subway.jsp");

rdp.forward(request, response);

 

} catch (Exception e) {

// Exception 처리 로직

e.printStackTrace();

}

return list;

}

 

public List SelectStation(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

dao=SubwayDAO.getInstance();

String line=request.getParameter("line"); //사용자가 선택한 특정 호선(=line)을 가져온다.

try {

List list=dao.SelectStation(line); //parameter로 line을 넘겨 DB에 조회

 

response.setContentType("text/html;charset=euc-kr");

response.setHeader("Cache-Control", "no-cache");

 

PrintWriter out=response.getWriter();

 

//JavaScript 배열 형식의 String 생성

//이 때, StringBuffer를 사용하는 이유는 Memory 낭비를 줄이기 위함.

StringBuffer sb=new StringBuffer();

sb.append("[");

 

for(int i=0; i<list.size();i++){

String station=(String)list.get(i);

sb.append("'"+station+"'");

if(i!=(list.size()-1)){

sb.append(",");

}

}

 

sb.append("]"); //최종적으로 ['A역','B역','C역' … 'z역'] 으로 sb에 저장된다. 이런 식으로 저장하는 이유는 javascript에서의 배열 형태를 의미.

 

out.println(sb.toString());

out.close();

} catch (SQLException e) {

// Exception 처리 로직

//RequestDispatcher rdp=request.getRequestDispatcher("error.jsp");

//rdp.forward(request, response);

e.printStackTrace();

}

return list;

}

}

 

Controller는 이제 DAO에 DB 관련 업무를 지시한다. 여기서는 DAO 관련 업무를 iBATIS OpenFrameWork로 구현한다.

이를 위해 우선적으로 WEB-INF/lib/에 ibatis-2.3.4.726.jar API 파일이 존재해야 한다.

그리고 DB와의 연결정보를 가진 SqlMapConfig.xml 파일과 Sql문들이 저장된 subway.xml 파일의 생성 및 설정이 필요하다.

SqlMapConfig.xml

<sqlMapConfig>

 

<transactionManager type="JDBC" commitRequired="false">

<dataSource type="SIMPLE">

<property name="JDBC.Driver" value="oracle.jdbc.driver.OracleDriver"/>

<property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@192.168.78.100:1521:XE"/>

<property name="JDBC.Username" value="hr"/>

<property name="JDBC.Password" value="hr"/>

</dataSource>

</transactionManager>

 

<sqlMap resource="config/subway.xml"/> //Sql문들이 저장된 resource 위치 지정.

 

</sqlMapConfig>

Subway.xml

<?xml version="1.0" encoding="UTF-8" ?>

 

<!DOCTYPE sqlMap

PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"

"http://ibatis.apache.org/dtd/sql-map-2.dtd">

 

<sqlMap>

<select id="selectAllLine" resultClass="string">

SELECT DISTINCT(LINE)

FROM SUBWAY

ORDER BY LINE ASC

</select>

 

<select id="stationOfselectedLine" resultClass="string">

SELECT station

FROM SUBWAY

WHERE LINE = #line#

</select>

</sqlMap>

 

이제 SubwayDAO.java 파일을 살펴본다.

 

package dao;

 

// import 정보생략

 

public class SubwayDAO {

private static SubwayDAO instance;

private SqlMapClient client;

 

private SubwayDAO(){

String sqlMapConfig="config/SqlMapConfig.xml";

try {

Reader reader = Resources.getResourceAsReader(sqlMapConfig);

client = SqlMapClientBuilder.buildSqlMapClient(reader);

} catch (IOException e) {

e.printStackTrace();

}

}

 

public static SubwayDAO getInstance() {

if (instance == null) {

instance = new SubwayDAO();

}

return instance;

}

 

public List SelectAllLine()throws Exception{

return client.queryForList("selectAllLine");

}

 

public List SelectStation(String line) throws SQLException{

return client.queryForList("stationOfselectedLine",line);

}

}

 

마지막으로 응답을 위한 subway.jsp 페이지를 작성한다. ( JSTL 사용을 위한 API들을 iBATIS API 복사위치로 복사한다.)

Subway.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"

pageEncoding="EUC-KR"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">

<title>Insert title here</title>

<script>

var xhr;

function getStation(){

//호선에 맞는 역을 조회하여 select 보여주는 function

 

//XMLHttpRequest 생성

if(window.ActiveXObject){

xhr=new ActiveXObject("Microsoft.XMLHTTP");

}else{

xhr=new XMLHttpRequest();

}

 

var lineSel=document.getElementById("line");

var line=lineSel.options[lineSel.selectedIndex].value;

//var line=document.getElementById("line").value; 된다.

 

//CallBack 설정

xhr.onreadystatechange=getData;

//Open & send

xhr.open("GET","subwayController?command=get_station&line="+line, false);

xhr.send(null);

}

 

//CallBack 함수

function getData(){

if(xhr.readyState==4){

if(xhr.status==200){

var station=eval(xhr.responseText);

//select 태그생성

var sel=document.createElement("select");

sel.setAttribute("name","station");

sel[0]=new Option("default","");

//select Option추가

for(i=0;i<station.length;i++){

sel[i+1]=new Option(station[i],station[i]);

}

var span=document.getElementById("station_span");

while(span.childNodes[0]){

span.removeChild(span.childNodes[0]);

}

span.appendChild(sel);

}

}

}

 

</script>

</head>

<body>

<font size="10" color="blue">지하철 노선 조회</font><br/>

<hr/>

 

<select id="line" name="line" onChange="getStation()">

<option value="default">호선 선택</option>

<!-- 나머지 option controller에서 request scope를통해 보내준 List 통해 만든다. 이를 위해 JSTL forEach 사용. -->

<c:forEach var="line" items="${requestScope.list}">

<option value="${line }">${line } 호선</option>

</c:forEach>

</select>

<!-- 선택된 라인에 맞는 역들을 select 출력 -->

<span id="station_span"></span>

</body>

</html>

 

실습결과