[2010.07.25 AJAX 최종 실습 예제]
1. Index.html에서 사용자는 '상품목록조회' Link를 선택하여 서버에 정보를 요구한다. |
2. 넘겨받은 Front Controller Servlet은 이를 자신이 직접 처리하지 않고, Service 역할을 하는 클래스에 위임한다.(MVC2 Pattern 적용) |
3. Controller로부터 위임받은 일이 DB와 관련된 일이므로 Service는 다시 DAO(DataAccessObject) 클래스에 위임한다. |
4. vice로부터 위임받은 일을 DAO는 iBATIS 프레임워크를 사용하여 DB에 해당 정보를 조회 후, 자신을 호출한 Service 클래스에 결과값을 return한다. |
5. Service는 다시 자신을 호출한 Controller에게 결과값을 반환한다. |
6. Controller는 넘겨받은 값을 다시 사용자에게 넘겨주기 위해 RequestDispatcher를 사용하여 결과값을 "category_list-json.jsp"에 Forward 한다. |
이를 구현하기 위한 파일 구조는 아래와 같다.
ETC. |
Servlet은 web.xml에서 /categoryController로 Mapping되어 있다.
| |
조회할 상품Table이 DB에 생성되어 있어야 한다.
|
1. Index.html에서 살펴보기
<a href="categoryController?command=first_category_json">상품 목록 조회 JSON</a> |
위 Link 태그에서 보듯이 index.html은 front controller 역할을 하는 CategoryController에게 parameter Name 'command'에 값을 'first_category_json'이라는 값을 가지고 넘어간다.
2. CategoryController에서는 Client로부터 요청받은 작업이 무엇인지 알기 위해서 command값을 분석하고 이에 맞는 Logic을 Service 클래스가 수행하도록 지시한다. (이 때 Singleton 처리 위해 init()에서 해당 객체를 미리 호출하여 사용한다.)
public void init(){ categoryService = CategoryService.getInstance(); productService = ProductService.getInstance(); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("euc-kr"); String command = request.getParameter("command"); if(command.equals("first_category_json")){ getFirstCategoryJSON(request,response); }else if(command.equals("second_category_json")){ getSecondCategoryJSON(request, response); }else if(command.equals("third_category_json")){ getThirdCategoryJSON(request, response); }else if(command.equals("get_product_list_by_third_category_id_JSON")){ getProductListByCategoryIdJSON(request, response); } }
public void getFirstCategoryJSON(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List firstList = null;
try { firstList = categoryService.getAllFirstCategory(); request.setAttribute("firstList", firstList); forward(request, response, "category_list_json.jsp", false);
} catch (SQLException e) { //error 처리 e.printStackTrace(); } }
|
3. Service에서는 객체 생성을 위한 singleton 처리 및 DAO에 작업처리를 요구한다. 또한 생성자에서 DAO 객체를 받아온다.
private static CategoryService service; private CategoryDAO dao; private CategoryService(){ dao = CategoryDAO.getInstance(); } public static CategoryService getInstance(){ if(service==null)service = new CategoryService(); return service; }
public List getAllFirstCategory() throws SQLException{ List list = dao.selectAllFirstCategory(); return list; } |
4. DAO에서는 iBATIS를 연동하여 DB에서 해당 Query의 결과값을 받아와 다시 service와 Controller에게 순서대로 넘겨준다.
public List selectAllFirstCategory()throws SQLException{ List list = sqlMap.queryForList("category.selectAllFirstCategory"); return list; } |
5. Controller에서는 이 값을 requestScope에 "firstList"라는 이름으로 저장한다.
firstList = categoryService.getAllFirstCategory(); request.setAttribute("firstList", firstList); |
6. 그리고 forward(request, response, "category_list_json.jsp", false); 명령으로 해당 페이지로 값을 넘긴다.
이로서 Server Layer에서의 작업은 끝나고 넘겨받은 값을 Client단의 JSP 페이지에서 출력하기 위해 AJAJ(Asyncronous Javascript And JSON)을 통해 처리하도록 한다.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
대분류 : <select name="first_category" id="first_category" onChange="getSecond()"> <OPTION VALUE='DEFAULT'>대분류</OPTION> <!--JSTL을 이용해 requestScope에 속성으로 등록된 대분류 데이터를 가져와 option 태그부분을 동적으로 생성한다. --> <!-- Map객체 형태로 넘어와 있음. --> <c:forEach var="firstList" items="${requestScope.firstList}"> <option value="${firstList.FIRST_CATEGORY_ID}">${firstList.FIRST_CATEGORY_NAME } </option> </c:forEach> </select>
var xhr; //XMLHttpRequest 객체 생성하여 xhr에 할당 function createXMLHttpRequest(){//추후 사용하게될 함수들에서 공통적으로 필요한 객체이므로 함수로 따로 빼서 호출! if(window.ActiveXObject){ xhr=new ActiveXObject("Microsoft.XMLHTTP"); }else{ xhr=new XMLHttpRequest();//IE8 버전에서는 이 객체도 사용가능 } |
위 과정을 통해 DB에서 1차 대분류값은 가져오게 된다.
이제 중분류를 가져오도록 해야 한다. 중분류를 가져오는 방법은 대분류에서 그림과 같이 특정 값이 선택되었을 때, 그 선택된 값을 가지고 DB에 다시 Query를 날리는 방식이다.
-
우선 대분류에서 특정 값이 선택되었을 때 서버단으로 그 값을 보내고 그 값을 기반으로 DB에서 서버단에서 넘어온 값을 사용자에게 보여줄 UI를 설정한다.
먼저 중분류가 표시될 UI를 SELECT 태그로 생성한다. 중분류 : <SELECT id="second_category" onChange="getThird()"><OPTION VALUE='DEFAULT'>중분류</OPTION></SELECT>
그리고 첫번째 대분류값이 변경되었을 때, 실행될 이벤트의 함수를 만든다.(이미 위에서 대분류 UI를 만들 때 onChange 이벤트핸들러에서 getSecond()를 선언하였다.
function getSecond(){ //사용자가 선택한 첫번째 카테고리(="대분류")를 변수에 저장한다. var fir=document.getElementById("first_category"); var firstCategory=fir.options[fir.selectedIndex].value;
//createXMLHttpRequest 객체 생성 createXMLHttpRequest(); //CallBack 함수 지정. xhr.onreadystatechange=getSecondCategory; //Open & send xhr.open("GET","categoryController?command=second_category_json&firstCategory="+firstCategory, false); xhr.send(null); }
function getSecondCategory(){ if(xhr.readyState==4){ if(xhr.status==200){ var secondCagegory = xhr.responseText; //(문자열로 넘어온)받아온 값 을 다시 JSON 값으로 변경해야 한다. var jsonData = eval("("+secondCagegory+")"); //중분류 select 객체 var sel=document.getElementById("second_category"); for(i=0; i<jsonData.secondCategory.length; i++){ sel[i+1]= new Option(jsonData.secondCategory[i].SECOND_CATEGORY_NAME,jsonData.secondCategory[i].SECOND_CATEGORY_ID); } } } } |
2. Open()에서 "categoryController?command=second_category_json&firstCategory="+firstCategory" 으로 Controller에게 넘어온 것을 이제 Controller가 다시 분석하여 해당 Logic들을 처리한다.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("euc-kr"); String command = request.getParameter("command");
if(command.equals("first_category_json")){ getFirstCategoryJSON(request,response); }else if(command.equals("second_category_json")){ getSecondCategoryJSON(request, response);
public void getSecondCategoryJSON(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=euc-kr"); response.setHeader("Cache-Control", "no-cache"); PrintWriter out = response.getWriter(); String firstCategory = request.getParameter("firstCategory");
try { String retValue = categoryService.getSecondCategoryJSON(firstCategory); out.println(retValue); out.flush(); out.close(); } catch (SQLException e) {//error 처리로직 e.printStackTrace(); } } |
3. Service 클래스
public String getSecondCategoryJSON(String firstCategory) throws SQLException{ JSONObject root = new JSONObject(); List list = dao.selectSecondCategoryByFirstCategoryId(firstCategory); //list : [{SECOND_CATEGORY_NAME=TV, SECOND_CATEGORY_ID=S-4}, {SECOND_CATEGORY_NAME=냉장고, SECOND_CATEGORY_ID=S-5}, {SECOND_CATEGORY_NAME=세탁기, SECOND_CATEGORY_ID=S-6}] //JSONObject를 완성한다. root.put("secondCategory", list);
return root.toString();//JSON 문자열 형태로 만들되, 이를 문자열(String)로 전송한다. 이를 javascript의 eval()을 통해 JSON 으로 다시 바꾸게 된다. } |
4. DAO 클래스
public List selectSecondCategoryByFirstCategoryId(String firstCategory) throws SQLException{ List list = sqlMap.queryForList("category.selectSecondCategoryByFirstCategoryId", firstCategory); return list; } |
이와 동일한 방법으로 소분류 역시 얻어오면 된다.
이제 마지막 소분류에서 해당 상품을 선택했을 때 아래와 같이 DB에서 상세정보를 가져와
, Table로 출력한다.
-
소분류에서 특정 값이 선택되었을 때(=onChange) 발생할 이벤트로서 getProductList() 이라는 이름으로 지정하였다.
<table border="1"> //위 Table의 틀을 생성. <thead id="thead"></thead> <tbody id="tbody"></tbody> </table>
//상품 리스트 조회 요청 //Controller에 client가 선택한 소분류 아이디를 넘긴다. function getProductList(){ createXMLHttpRequest(); var cmd = "get_product_list_by_third_category_id_JSON"; var tsel = document.getElementById("third_category"); var value = tsel.options[tsel.selectedIndex].value; var url = "categoryController?command="+cmd+"&thirdCategory="+value; xhr.onreadystatechange=getProductListByThirdCategory; xhr.open("GET",url, false); xhr.send(null); }
//상품 리스트 응답 데이터 처리 //controller가 보낸 Data를 가지고 상품 리스트 Table을 만든다. function getProductListByThirdCategory(){ if(xhr.readyState==4){ if(xhr.status==200){ var txt = xhr.responseText; var jsonData = eval("("+txt+")"); //thead var thead = document.getElementById("thead"); var tr = document.createElement("tr"); var td1 = document.createElement("td");//id var td2 = document.createElement("td");//name var td3 = document.createElement("td");//maker var td4 = document.createElement("td");//price td1.innerHTML = "제품 ID"; td2.innerHTML = "제품명"; td3.innerHTML = "제조사"; td4.innerHTML = "제품가격"; //td->tr tr.appendChild(td1); tr.appendChild(td2); tr.appendChild(td3); tr.appendChild(td4); //tr->thead 붙이기 전에 삭제 while(thead.firstChild){ thead.removeChild(thead.firstChild); } thead.appendChild(tr); //tbody var tbody = document.getElementById("tbody"); //tr->tbody 붙이기 전에 삭제 while(tbody.firstChild){ tbody.removeChild(tbody.firstChild); } for(i = 0; i<jsonData.ITEM_LIST.length;i++){ thead = document.getElementById("thead"); tr = document.createElement("tr"); td1 = document.createElement("td");//id td2 = document.createElement("td");//name td3 = document.createElement("td");//maker td4 = document.createElement("td");//price
td1.innerHTML = jsonData.ITEM_LIST[i].id; td2.innerHTML = jsonData.ITEM_LIST[i].name; td3.innerHTML = jsonData.ITEM_LIST[i].maker; td4.innerHTML = jsonData.ITEM_LIST[i].price; tr.appendChild(td1); tr.appendChild(td2); tr.appendChild(td3); tr.appendChild(td4); tbody.appendChild(tr); } } } } |
2. Controller에서 해당 넘어온 command 값과 사용자가 선택한 소분류의 값을 받아 처리한다.
}else if(command.equals("get_product_list_by_third_category_id_JSON")){ getProductListByCategoryIdJSON(request, response); }
public void getProductListByCategoryIdJSON(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=euc-kr"); response.setHeader("Cache-Control", "no-cache"); PrintWriter out = response.getWriter(); String thirdCategory = request.getParameter("thirdCategory");
try { String retValue = productService.getProductInfoByCategoryIdJSON(thirdCategory); out.println(retValue); out.flush(); out.close(); } catch (SQLException e) { //error 처리 e.printStackTrace(); } } |
3. Service 클래스
/** 소분류를 통해 상품 리스트를 조회 처리하는 Business Service 메소드 * 결과를 JSON 객체형태로 작성한다.*/
public String getProductInfoByCategoryIdJSON(String categoryId) throws SQLException{ List list = dao.selectProductInfoByCategory(categoryId); JSONObject jobj = new JSONObject();//상품 목록 전체를 담을 JSONObject JSONArray jList = new JSONArray(); //각 상품 정보를 담을 JSONArray for(Object obj : list){ ProductVO pvo = (ProductVO)obj; JSONObject o = new JSONObject(); o.put("id", pvo.getProductId()); o.put("name", pvo.getProductName()); o.put("maker", pvo.getProductMaker()); o.put("price", pvo.getProductPrice()); jList.add(o); } jobj.put("ITEM_LIST", jList); System.out.println(jobj.toString()); return jobj.toString();
} |
4. DAO 클래스
public List selectProductInfoByCategory(String categoryId) throws SQLException{ List list = sqlMap.queryForList("product.selectProductInfoByCategory", categoryId); return list; } |
'Java > Source_book' 카테고리의 다른 글
[javascript] 초간단 객체지향 JavaScript (0) | 2013.05.13 |
---|---|
2010.07.23 DWR(Direct Web Remoting) (0) | 2010.07.26 |
2010.07.21 Ajax DOM 을 이용한 동적으로 Table 생성 및 JSON (0) | 2010.07.21 |
[ 2010.07.19 - 20 AJAX 실습 및 정리 ] – Word 버전 (0) | 2010.07.20 |
[2010.07.19 ~20]JavaScript & Ajax - Image 버전 (0) | 2010.07.20 |
2010.07.19 AJAX (0) | 2010.07.19 |