새로고침(Reload) 하지않아도 글을 작성 시 밑에 조회가 되도록 구현해보자.
개발 환경 셋팅
톰캣 7.0, 이클립스, 오라클, JDK 7.x, Struts2, Spring2.5, iBatis
구현 순서
1. [DB] 사용할 테이블 생성 - iguest
2. DTO 생성 - GuestDTO.class
3. 페이징 처리를 위한 클래스 생성 - MyUtil.class
4. [jsp 페이지 생성] 방명록 작성/조회 페이지 - guest.jsp
5. [jsp 페이지 생성] DB에 접근하여 방명록이 작성되어 div태그로 작성되는 페이지 - list.jsp
6. [iBatis] iguest_sqlMap.xml 작성
7. [iBatis] sqlMap_config.xml에 resource 등록 (iguest_sqlMap.xml)
8. Action클래스 생성
9. [struts2] struts환경설정 - struts-iguest.xml 생성 및 등록
10. 스트럿츠가 아닌 스프링에서 객체 생성시 - action-Context.xml
1. DataBase - 사용할 iguest 테이블 생성
create table iguest( num NUMBER(9), name VARCHAR2(25), email VARCHAR2(50), content VARCHAR2(4000), ipAddr VARCHAR2(50), created DATE, CONSTRAINT pk_iguest_num PRIMARY KEY(num)); |
2. DTO생성 - GuestDTO.class
package com.iguest; public class GuestDTO { private int listNum; private int num; private String name; private String email; private String content; private String ipAddr; private String created; private String pageNum; getter/setter 작성 } |
3. 페이징 처리를 위한 클래스 생성 - MyUtil.class
package com.util; import org.springframework.stereotype.Service; @Service("myUtil") public class MyUtil { //전체페이지 수 구하기 //numPerPage : 한 화면에 표시할 데이터 갯수 //dataCount : 전체 데이터 갯수 public int getPageCount(int numPerPage, int dataCount){ int pageCount = 0; pageCount = dataCount / numPerPage; if(dataCount % numPerPage != 0) pageCount++; return pageCount; } //페이징 처리 //currentpage : 현재 표시할 페이지 //totalPage : 전체 페이지 수 //listUrl : 링크를 설정한 URL //자바스크립트를 이용하여 변환 public String pageIndexList(int currentPage, int totalPage){ int numPerBlock = 5; int currentPageSetup; int n; int page; String strList=””; if(currentPage==0) return ""; //표시할 첫 페이지 currentPageSetup = (currentPage/numPerBlock)*numPerBlock; if(currentPage%numPerBlock==0) currentPageSetup = currentPageSetup - numPerBlock; //1페이지 if((totalPage>numPerBlock)&&(currentPageSetup>0)){ strList = "<a onclick='listPage(1);'>1</a>"; } //◀: 총페이지수가 numPerBlock 이상인 경우 이전 numPerBlock(게시글5개)을 보여줌 n = currentPage - numPerBlock; //자바스크립트에 listPage라는 function을 정의하여 사용할 것이므로 a태그에 작성 if((totalPage>numPerBlock)&&(currentPageSetup>0)){ strList = "<a onclick='listPage("+n+");'>◀</a>"; } //바로가기 페이지 page = currentPageSetup + 1; while((page<=totalPage)&&(page<=currentPageSetup+numPerBlock)){ if(page==currentPage){ strList += "<font color='Fuchsia'>" +page+"</font>"; }else{ strList += "<a onclick='listPage("+page+");'>"+page+"</a>"; } page++; } //▶: 총페이지수가 numPerBlock 페이지 이상인 경우 다음 numPerBlock 페이지를 보여줌 n = currentPage + numPerBlock; if(totalPage - currentPageSetup > numPerBlock){ strList += "<a onclick='listPage(" +n+");'>▶</a>"; } //마지막페이지 //총페이지수가 numPerBlock 페이지 이상이고 현재페이지+한페이지당갯수보다 크면 출력 if((totalPage>numPerBlock)&&(currentPageSetup+numPerBlock<totalPage)){ strList += "<a onclick='listPage("+totalPage+");'>"+totalPage+"</a>"; } return strList; } } |
4. jsp 페이지 생성 - 방명록 작성/조회 페이지(guest.jsp)
<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% request.setCharacterEncoding("UTF-8"); String cp = request.getContextPath(); %> <!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=UTF-8"> <title>방명록</title> <link rel="stylesheet" href="<%=cp%>/data/css/style.css" type="text/css"> <script type="text/javascript" src="<%=cp%>/data/js/jquery-3.3.1.min.js"></script> <script type="text/javascript"> $(function(){ listPage(1);//첫 실행시 페이지=1로 실행 }); $(function(){ $("#sendButton").click(function(){ var params = "name=" + $("#name").val() + "&email=" + $("#email").val() + "&content=" + $("#content").val(); $.ajax({ type:"POST", url:"<%=cp%>/iguest/created.action", data:params, success:function(args){ //넘어온값이 args에 담겨있음 $("#listData").html(args); //초기화 방명록이 작성된 뒤 DB에 데이터가 반영이 되고 입력창에 있는 데이터값은 지워져야 한다. 하지만 reload 개념이 아니어서 input 태그에 입력된 데이터를 없애주는 소스가 필요하다. $("#name").val(""); $("#email").val(""); $("#content").val(""); $("#name").focus(); }, beforeSend:showRequest, error:function(e){ alert(e.responseText); } }); }); }); function showRequest(){ //beforesend : 보내기전에 실행되는 함수 var name = $.trim($("#name").val());//Ajax에서 제공하는 trim함수 var email = $.trim($("#email").val()); var content = $.trim($("#content").val()); if(!name){ alert("\n이름을 입력하세요."); $("#name").focus(); return false;//null이므로 진행 중단 } if(!content){ alert("\n내용을 입력하세요."); $("#content").focus(); return false;//null이므로 진행 중단 } if(content.length>200){ alert("\n내용을 200자 이내로 입력하세요."); $("#content").focus(); return false;//null이므로 진행 중단 } return true; } function listPage(page){ var url = "<%=cp%>/iguest/list.action"; $.post(url,{pageNum:page},function(args){ $("#listData").html(args); }); $("#listData").show();//display:block으로 프로퍼티를 설정한 것과 동일한 효과 } function deleteData(num,page){ //삭제 후 페이지 이동 필요 var url = "<%=cp%>/iguest/deleted.action"; $.post(url,{num:num,pageNum:page},function(args){ $("#listData").html(args); }); } </script> </head> <body> <br><br> <table width="600" border="2" cellpadding="0" cellspacing="0" bordercolor="#e6d4a6" align="center"> <tr height="40"> <td style="padding-left: 20px;">방 명 록</td> </tr> </table> <br><br> <table width="600" border="0" cellpadding="0" cellspacing="0" align="center"> <tr> <td width="600" colspan="4" height="3" bgcolor="#e6d4a6"></td> </tr> <tr> <td width="60" height="30" bgcolor="#eeeeee" align="center">작성자</td> <td width="240" height="30" style="padding-left: 10px;"> <input type="text" id="name" size="35" maxlength="20" class="boxTF"> </td> <td width="60" height="30" bgcolor="#eeeeee" align="center">email</td> <td width="240" height="30" style="padding-left: 10px;"> <input type="text" id="email" size="35" maxlength="20" class="boxTF"> </td> </tr> <tr><td width="600" colspan="4" height="1" bgcolor="#e6d4a6"></td></tr> <tr> <td width="60" height="30" bgcolor="#eeeeee" align="center">내용</td> <td width="540" colspan="3" style="padding-left: 10px;"> <textarea id="content" rows="3" cols="84" class="boxTA"></textarea> </td> </tr> <tr><td width="600" colspan="4" height="1" bgcolor="#e6d4a6"></td></tr> <tr> <td width="600" colspan="4" height="30" align="right" style="padding-right: 15px;"> <input type="button" value="등록하기" class="btn2" id="sendButton"/> </td> </tr> </table> <br/> <span id="listData" style="display: none;"></span> </body> </html> |
5. jsp페이지 생성 - DB에 접근하여 방명록이 리스트가 div태그로 작성되는 페이지(list.jsp)
<c:if test="${totalDataCount!=0 }"> <table width="600" border="0" cellpadding="0" cellspacing="0" align="center"> <c:forEach var="dto" items="${lists }"> <tr> <td colspan="2" bordercolor="#999999" height="1"></td> </tr> <tr height="30"> <td width="300" style="padding-left: 10px;"> No ${dto.listNum }.${dto.name }(<a href="mailto:${dto.email }">${dto.email }</a>) </td> <td width="300" align="right" style="padding-right: 10px;"> ${dto.created } <a href="javascript:deleteData('${dto.num }','${pageNum }')">삭제</a> </td> </tr> <tr> <td height="30" style="padding-left: 10px;" colspan="2"> ${dto.content } </td> </tr> </c:forEach> <tr> <td colspan="2" bordercolor="#dbdbdb" height="2"></td> </tr> <tr height="30"> <td align="center" colspan="2"> ${pageIndexList } </td> </tr> </table> </c:if> |
6. iguest_sqlMap.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 namespace="iguest"> <select id="numMax" resultClass="int"> select nvl(max(num),0) from iguest </select> <select id="dataCount" resultClass="int"> select count(*) from iguest </select> <insert id="insertData" parameterClass="com.iguest.GuestDTO"> insert into iguest (num, name, email, content, ipAddr, created) values(#num#,#name#,#email#, #content#,#ipAddr#,sysdate) </insert> <select id="listData" parameterClass="map" resultClass="com.iguest.GuestDTO"> select * from( select rownum rnum, data.* from( select num,name,email,content,ipAddr,created from iguest order by num desc) data ) <![CDATA[ where rnum>=#start# and rnum<=#end# ]]> </select> <delete id="deleteData" parameterClass="int"> delete iguest where num=#num# </delete> </sqlMap> |
7. iguest_sqlMap.xml 등록(sqlMap_config.xml)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig> <settings cacheModelsEnabled="false" useStatementNamespaces="true"/> <sqlMap resource="com/util/sqlMap/temp_sqlMap.xml"/> <sqlMap resource="com/util/sqlMap/board_sqlMap.xml"/> <sqlMap resource="com/util/sqlMap/iguest_sqlMap.xml"/> </sqlMapConfig> |
8. Action클래스 생성
package com.iguest; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import com.opensymphony.xwork2.Preparable; import com.util.MyUtil; import com.util.dao.CommonDAO; public class GuestAction extends ActionSupport implements Preparable, ModelDriven<GuestDTO>{ private static final long serialVersionUID = 1L; private GuestDTO dto; Ajax가 데이터를 넘김으로 Getter는 불필요함@Resource(name="dao") private CommonDAO dao; @Resource(name="myUtil") private MyUtil myUtil; @Override public GuestDTO getModel() { return dto; } @Override public void prepare() throws Exception { dto = new GuestDTO(); } //방명록 입력 public String created() throws Exception { HttpServletRequest request = ServletActionContext.getRequest(); int maxNum = dao.getIntValue("iguest.numMax"); dto.setNum(maxNum+1);//게시물번호 dto.setIpAddr(request.getRemoteAddr()); dao.insertData("iguest.insertData", dto); return list();//DB입력 완료후 redirect를 하면 새로고침됨(페이지 reload). Ajax로 구현하기 위해서 메소드 호출로 변경 } //방명록 리스트 조회 public String list() throws Exception { HttpServletRequest request = ServletActionContext.getRequest(); int numPerPage = 5; int totalPage = 0; int totalDataCount =0; String pageNum = request.getParameter("pageNum");//삭제에서만 넘어옴 int currentPage = 1; if(pageNum!=null&&pageNum!=""){ currentPage = Integer.parseInt(pageNum); }else{ pageNum = "1"; } totalDataCount = dao.getIntValue("iguest.dataCount"); if(totalDataCount!=0){ totalPage = myUtil.getPageCount(numPerPage, totalDataCount); } //삭제 진행되어 현재페이지 없어질경우 if(currentPage>totalPage) currentPage = totalPage; Map<String,Object> hMap = new HashMap<String,Object>(); int start = (currentPage-1)*numPerPage+1; int end = currentPage*numPerPage; hMap.put("start",start); hMap.put("end", end); List<Object> lists = (List<Object>)dao.getListData("iguest.listData",hMap); int listNum,n=0; Iterator<Object> it = lists.iterator(); while(it.hasNext()){ GuestDTO vo = (GuestDTO)it.next(); listNum = totalDataCount - (start+n-1); vo.setListNum(listNum); vo.setContent(vo.getContent().replaceAll("\n", "<br/>")); n++; } //페이징처리는 자바스크립트로 진행 String pageIndexList = myUtil.pageIndexList(currentPage, totalPage); request.setAttribute("lists", lists); request.setAttribute("pageIndexList",pageIndexList); request.setAttribute("totalDataCount", totalDataCount); request.setAttribute("pageNum", pageNum); return SUCCESS; } //삭제 public String deleted() throws Exception { HttpServletRequest request = ServletActionContext.getRequest(); int num = Integer.parseInt(request.getParameter("num")); dao.deleteData("iguest.deleteData",num); //redirect하지 않고 list로 연동 return list(); } } |
9. struts 환경설정 - struts-iguest.xml 생성
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="iguest" extends="default" namespace="/iguest" > <action name="guest"> <result>/iguest/guest.jsp</result> </action> <action name="created" method="created" class="com.iguest.GuestAction"> <interceptor-ref name="myPrepareParamsStack"/> <result>/iguest/list.jsp</result> </action> <action name="list" method="list" class="com.iguest.GuestAction"> <result>/iguest/list.jsp</result> </action> <action name="deleted" method="deleted" class="com.iguest.GuestAction"> <result>/iguest/list.jsp</result> </action> </package> </struts> |
9. struts환경설정 - struts.xml에 등록
<include file="struts-iguest.xml"/> |
10.스프링에서 객체 생성시 - action-Context.xml에 작성
<bean id="GuestAction" class="com.board.GuestAction" scope="prototype"/> |
구현 페이지
전체 흐름
★ guest.action을 호출하면 guest.jsp 페이지가 호출된다 .
<action name="guest">
<result>/iguest/guest.jsp</result>
</action>
★ guest.jsp 에서 페이지가 로드될 때, listPage 함수를 실행하도록 작성하였다.
$(function(){
listPage(1);//첫 실행시 페이지=1로 실행
});
1. listPage 메소드는 list.action을 호출.
2. list.actiondms GuestAction클래스의 list메소드를 실행한 뒤 result로 iguest.jsp 페이지를 반환한다.
3. 작성된 방명록이 있을 경우 list.jsp에 해당태그들이 반복문이 돌아가면서 작성된다
4. 작성된 태그들은 id=listData인 <span>태그에 innerHtml에 저장된다.
5. <span>의 display 속성을 block으로 변경한다.
▶ 페이지가 새로고침 되지않아도 비동기식을 활용하여 방명록이 업데이트되는 모습을 확인할 수 있다.
'Dev > JS & Jquery' 카테고리의 다른 글
[javascript] 콜백지옥을 탈출하는 q.js (0) | 2020.02.18 |
---|---|
Ajax - JSON을 활용하여 자바스크립트의 객체 생성 (0) | 2019.04.03 |
Ajax - 자바스크립트 클래스 만들기 (0) | 2019.04.03 |
Ajax - Document Object Model과 XML (0) | 2019.04.03 |
Ajax - 검색시 제시어 기능 만들기 (0) | 2019.04.02 |