실제폴더: /ibbs, 가상주소(uri): /comm
개발환경: struts2+spring2.0, 톰캣 v8.5, iBatis, 이클립스, JDK 7.x
- struts-ibbs.xml (
BoardAction.java, CommentList.java
1. DB설정
ibbs_sqlMap.xml (sqlMapConfig.xml 에 등록)
2. xml파일
struts-ibbs.xml (struts.xml 에 등록)
3. Action클래스 생성
BoardAction.java, CommentAction.java
4. 게시글 관련 jsp 페이지
list.jsp, created.jsp, article.jsp
5. 댓글관련 jsp 페이지
- article.jsp (게시글 부분과 공통)
- ajax를 통해 데이터를 반환할 때, 표 형식으로 만들어서 보내기 위한 페이지 - commentList.jsp
1. DB - 사용할 테이블 생성
게시글 테이블
CREATE TABLE ibbs (
boardNum NUMBER(9) NOT NULL
,name VARCHAR2(20) NOT NULL
,email VARCHAR2(50)
,subject VARCHAR2(50) NOT NULL
,content VARCHAR2(4000) NOT NULL
,ipAddr VARCHAR2(20) NOT NULL
,hitCount NUMBER(9) NOT NULL
,created DATE
,CONSTRAINT pk_ibbs_boardNum PRIMARY KEY(boardNum)
);
댓글 테이블
CREATE TABLE ibbsComment (
commentNum NUMBER(9) NOT NULL
,boardNum NUMBER(9) NOT NULL
,name VARCHAR2(20) NOT NULL
,content VARCHAR2(100) NOT NULL
,ipAddr VARCHAR2(20) NOT NULL
,created DATE
,CONSTRAINT pk_ibbsComment_commentNum PRIMARY KEY(commentNum)
,CONSTRAINT fk_ibbsComment_boardNum FOREIGN KEY(boardNum)
REFERENCES ibbs(boardNum) ON DELETE CASCADE
);
CommonDAOImpl.java - DB 접근 객체 생성
//CommonDAO dao = new CommonDaoImpl() 할 필요 없이 spring이 "dao"(사용자정의) 라는 이름으로 객체생성을 해줌 => 나는 갖다 써주기만 하면됨
//이름 안써주면, 클래스명인 CommonDAOImpl로 객체생성이 되어버리므로 나중에 서로다른페이지에서 갖다쓸 때 충돌이 일어날 수 있음
@Repository("dao")
public class CommonDAOImpl implements CommonDAO{
@Autowired // aplicationContext.xml로 가서, 너가 알아서 이 이름 객체 찾아와서 초기화 시켜
private SqlMapClientTemplate sqlMapClientTemplate;
// 원래는, setter도 있어야함
//public void setSqlMapClientTemplate() {..}
// 지금은 annotation 쓸거니깐 필요없음
...
}
MyUtil.java - 페이징 처리
@Service("myUtil")
public class MyUtil {
...
}
게시글 작성
struts-ibbs.xml
<action name="created" class="com.ibbs.BoardAction" method="created">
<interceptor-ref name="myPrepareParamStack"/>
<result name="input">/ibbs/created.jsp</result>
<result name="success" type="redirectAction">list</result>
</action>
BoardAction.java
package com.ibbs;
import java.net.URLDecoder;
import java.net.URLEncoder;
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 BoardAction extends ActionSupport
implements Preparable,ModelDriven<BoardDTO>{
private static final long serialVersionUID = 1L;
private BoardDTO dto; // 원본글
//CommonDAO => 이제 메소드마다 만들필요 없이 spring이 만들어놓은 객체를 가져다 쓰면 됨
// --- spring의 유일한 강점 코딩 (객체 생성) --
// 불러오면 객체가 Object 형태로 만들어져 있음 (내가 안 만든건 다 Object임)
@Resource(name="dao")
private CommonDAO dao; // 모든 메소드에서 이 dao를 사용해주면 됨
@Resource(name="myUtil")
private MyUtil myUtil;
@Override
public BoardDTO getModel() {
return dto;
}
@Override
public void prepare() throws Exception {
dto = new BoardDTO();
}
public String created() throws Exception {
HttpServletRequest request =
ServletActionContext.getRequest();
if (dto == null || dto.getMode()==null || dto.getMode().equals("")) {
dto.setMode("created");
request.setAttribute("dto", dto);
return INPUT;
}
int numMax = dao.getIntValue("ibbs.numMax");
dto.setBoardNum(numMax+1);
dto.setIpAddr(request.getRemoteAddr());
dao.insertData("ibbs.insertData", dto);
return SUCCESS;
}
.....................
}
created.jsp - mode로 "created"를 받아온 상황
1) created로 들어왔을 때 보여지는 창
<!-- 공통 (created, updated 중 어떤 걸로 들어온건지) -->
<input type="hidden" name="mode" value="${mode }" />
<c:if test="${dto.mode=='created'}">
<input type="button" value="등록하기" class="btn2" onclick="sendIt();" />
<input type="reset" value="다시입력" class="btn2"
onclick="document.myForm.subject.focus();" />
<input type="button" value="작성취소" class="btn2"
onclick="javascript:location.href='<%=cp%>/comm/list.action';" />
</c:if>
2) 등록하기 btn을 누르면 form 안의 input값들을 가지고 해당 url로 감
// 실제폴더: ibbs, 가상주소(uri): comm
if(f.mode.value=="created")
f.action = "<%=cp%>/comm/created.action";
게시글 리스트
struts-ibbs.xml
<action name="list" class="com.ibbs.BoardAction" method="list">
<interceptor-ref name="myPrepareParamStack"/>
<result name="success">/ibbs/list.jsp</result>
</action>
BoardAction.java - boardNum들에 대한 각각의 댓글 개수들도 가지고 와야 함
public String list() throws Exception {
HttpServletRequest request =
ServletActionContext.getRequest();
String cp = request.getContextPath();
int numPerPage = 3;
int totalPage = 0;
int totalDataCount = 0;
String searchKey = request.getParameter("searchKey");
String searchValue = request.getParameter("searchValue");
String pageNum = request.getParameter("pageNum");
if (searchValue == null) {
searchKey="subject";
searchValue="";
}
if(request.getMethod().equalsIgnoreCase("GET"))
searchValue = URLDecoder.decode(searchValue, "UTF-8");
int currentPage = 1;
if (pageNum!=null)
currentPage = Integer.parseInt(pageNum);
Map<String, Object> hMap = new HashMap<String, Object>();
hMap.put("searchKey", searchKey);
hMap.put("searchValue", searchValue);
totalDataCount =
dao.getIntValue("ibbs.dataCount", hMap);
if(totalDataCount!=0)
totalPage = myUtil.getPageCount(numPerPage, totalDataCount);
if(currentPage>totalPage)
currentPage = totalPage;
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("ibbs.listData", hMap);
// 글 하나 삭제 시, 일련번호 맞추기 위한 코드
int listNum,n=0;
int commentSu; // 댓글 수
int a = 0;
Iterator<Object> it = lists.iterator();
while(it.hasNext()) {
BoardDTO listDTO = (BoardDTO)it.next();
// 이걸 dto라고 변수명을 지어주면 자동으로 넘겨주는 dto와 이것이
// 충돌날 수도 있음. 그래서 listDTO 라고 지음
// 1. listNum 작업
listNum = totalDataCount-(start+n-1);
listDTO.setListNum(listNum);
n++;
// 2. 댓글(2) 작업 : sql접근
a = listDTO.getBoardNum();
commentSu = dao.getIntValue("ibbs.dataCount2", a); // 댓글 수
listDTO.setCommentNum(commentSu); // 해당 boardNum의 댓글 수 넣음
}
String params="";
String urlArticle = "";
String urlList = "";
if(!searchValue.equals("")) {
params = "searchKey="+searchKey;
params += "&searchValue=" +
URLEncoder.encode(searchValue, "UTF-8");
//encode한 상태로 uri에 넣어야함
}
// ◀이전 6 7 8 9 10 다음▶ 표시 링크
urlList = cp + "/comm/list.action";
urlArticle =
cp + "/comm/article.action?pageNum="+currentPage;
// 검색해서 들어온거면,
if(!params.equals("")) {
urlList += "?" + params;
urlArticle += "&" + params;
}
//param 라는 변수는 struts2가 내부적으로 사용하는 변수여서,
// setAttribute로 param 넘기면 안됨.
// 여기서 만약 dto를 넘기고 싶으면 위에 getter 안만들어줬기 때문에
// 수동으로 해야함 request.setAttribute("dto",dto);
request.setAttribute("lists", lists);
request.setAttribute("totalDataCount", totalDataCount);
request.setAttribute("pageIndexList",
myUtil.pageIndexList(currentPage, totalPage, urlList));
request.setAttribute("urlArticle", urlArticle);
request.setAttribute("params", params);
request.setAttribute("pageNum", currentPage);
request.setAttribute("searchKey", searchKey);
request.setAttribute("searchValue", searchValue);
return SUCCESS;
}
list.jsp
<div id="bbsList_list">
<div id="title">
<dl>
<dt class="num">번호</dt>
<dt class="subject">제목</dt>
<dt class="name">작성자</dt>
<dt class="created">작성일</dt>
<dt class="hitCount">조회수</dt>
</dl>
</div>
<div id="lists">
<c:forEach var="dto" items="${lists }">
<dl>
<dd class="num">${dto.listNum}</dd>
<dd class="subject">
<a href="${urlArticle }&boardNum=${dto.boardNum}">
${dto.subject } (${dto.commentNum })
</a>
</dd>
<dd class="name">${dto.name }</dd>
<dd class="created">${dto.created }</dd>
<dd class="hitCount">${dto.hitCount }</dd>
</dl>
</c:forEach>
</div>
<div id="footer">
<p>
<c:if test="${totalDataCount!=0 }">
${pageIndexList }
</c:if>
<c:if test="${totalDataCount==0 }">
등록된 게시물이 없습니다.
</c:if>
</p>
</div>
</div>
게시글 수정
article.jsp - 에서 [수정] 버튼을 누르면
<div id="bbsArticle_footer">
<div id="leftFooter">
<input type="button" value=" 수정 " class="btn2" onclick="sendData('updated');"/>
<input type="button" value=" 삭제 " class="btn2" onclick="sendData('deleted');"/>
</div>
function sendData(value) {
var boardNum = "${dto.boardNum}";
// javascript에서도 넘어오는 데이터에 대해서
//이렇게 el로 받을 수 있다.
var url = "<%=cp%>/comm/";
if (value == "updated")
url += "updated.action?";
else if (value == "deleted")
url += "deleted.action?";
url += "boardNum=" + boardNum;
//url += "&${params}"; // pageNum, sK, sV 넘어온거
url +="&pageNum=${pageNum}&searchKey=${searchKey}&searchValue=${searchValue}"
location.replace(url); // 이동
}
struts-ibbs.xml
<action name="updated" method="updated" class="com.ibbs.BoardAction">
<interceptor-ref name="myPrepareParamStack"/>
<result name="input">/ibbs/created.jsp</result>
<result name="success" type="chain">
list
</result>
</action>
--북마크
댓글 삭제 부분
commentList.jsp
<a href="javascript:deleteData('${dto.commentNum }','${pageNum }','${dto.boardNum }');">
삭제
</a>
article.jsp
function deleteData(num,page,boardNum) {
var url = "<%=cp%>/comm/deleted2.action";
//jQuery로만 ajax를 만들 때 사용
//[변수명:데이터]
$.post(url,{num:num,pageNum:page,boardNum:boardNum},function(args) {
// js특징중하나
//url 에 pageNum,page를 가지고 들어가서
//결과를 바로 받아온다 (보내는애와 받는애가 같이 있는 구조)
$("#listData").html(args);
});
$("#listData").show();
}
struts-ibbs.xml
<action name="deleted2" class="com.ibbs.CommentAction" method="deleted">
<result>/ibbs/commentList.jsp</result>
</action>
CommentAction.java
public String deleted() throws Exception {
HttpServletRequest request =
ServletActionContext.getRequest();
// 그 다음 경로는 같은 페이지 내의 함수인 list()로 보내므로
//매개변수로 넘어온 boardNum, pageNum, num 전부 다 받고
// 다시 request.setAttribute로 해주지 않아도 됨
int num = Integer.parseInt(request.getParameter("num"));
dao.deleteData("ibbs.deleteData2", num);
return list();
}
댓글 작성 부분
article.jsp
<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>
</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 rows="3" cols="84" class="boxTA" style="height: 50px;" id="content">
</textarea>
</td>
</tr>
<tr>
<td width="600" colspan="4" height="1" bgcolor="#e6d4a6"></td>
</tr>
<tr>
<td width="600" height="30" colspan="4" align="right" style="padding-right: 15px;">
<input type="button" value="등록하기" class="btn2" id="sendButton"/>
</td>
</tr>
</table>
[등록하기] 버튼 누르면,
$(document).ready(function(){
$("#sendButton").click(function(){
// jQuery의 사용자가 아래서 입력한 데이터를 받아오는 방식
// javascript는 document.getElementById 이렇게 접근했었음
var params = "name=" + $("#name").val()
+ "&content=" + $("#content").val()
+ "&boardNum=${dto.boardNum}";
$.ajax({
type:"POST", // input값 보내는거니깐 post형태로 보내기
url:"<%=cp%>/comm/created2.action",
data:params,
success:function(args){
// 결과 데이터는 이미 표로 가공된 상태로 올 것임 (commentList.jsp로부터)
$("#listData").html(args);
//ajax부분만 바뀌기 때문에, 사용자가 댓글 [등록하기] 누르고 나면
//입력창에 입력값이 그대로 남아있음 => 초기화 시켜주는 작업 필요
$("#name").val("");
$("#content").val("");
$("#name").focus; // 다 지우고 name에다가 커서 갖다놓기
},
beforeSend:showRequest, // 보내기전에 실행
error:function(e) {
alert(e.responseText); // 갔다와서 에러가 나면 알람을 띄워라
}
});
});
});
function showRequest() {
// 사용자가 입력한 데이터 가져와라
// 공백 없앤 상태로 변수에 다시 넣어줌
var name = $.trim($("#name").val());
var content = $.trim($("#content").val());
if(!name) {
alert("\n이름을 입력하세요!");
$("#name").focus;
return false;
}
if (!content) {
alert("\n내용을 입력하세요!");
$("#content").focus;
return false;
}
if (!content.length > 200) {
alert("\n내용을 200자까지만 입력 가능합니다!");
$("#content").focus;
return false;
}
// true가 돌아가야만, 서버로 값을 보냄
return true;
}
struts-ibbs.xml
<action name="created2" class="com.ibbs.CommentAction" method="created">
<interceptor-ref name="myPrepareParamStack"/>
<result>/ibbs/commentList.jsp</result>
</action>
CommentAction.java
public String created() throws Exception {
HttpServletRequest request =
ServletActionContext.getRequest();
// ajax에 의해 넘어온 값: name, content, boardNum
// CommentDTO dto에 알아서 들어가는듯.
int numMax2 = dao.getIntValue("ibbs.numMax2");
dto.setCommentNum(numMax2+1);
dto.setIpAddr(request.getRemoteAddr());
dao.insertData("ibbs.insertData2", dto);
//redirect : client한테 주소 다시 한번 호출해 (화면 전체가 새로고침 되어버림)
//지금 쓰고 있는건 ajax이고
//ajax를 쓰는 이유는 새로고침 안 하려는게 크니까 redirect 쓰면 안됨
return list();
}
ibbs_sqlMap.xml
<select id="numMax2" resultClass="int">
select nvl(max(commentNum),0) from ibbsComment
</select>
<insert id="insertData2" parameterClass="com.ibbs.CommentDTO">
insert into ibbsComment (commentNum, boardNum, name, content, ipAddr, created) values
(#commentNum#, #boardNum#, #name#, #content#, #ipAddr#, sysdate)
</insert>
'Ajax & jQuery' 카테고리의 다른 글
Ajax - 방명록 만들기 (댓글창 만들기) (0) | 2019.10.27 |
---|---|
Ajax(5) - Document Object Model (DOM), DOM API를 이용한 XML 파싱 (pdf파일로부터 내용 더 보완하기) (0) | 2019.10.24 |
Ajax(4) - JSON형식 데이터를 읽어와 Javascript의 객체 생성 하기 (0) | 2019.10.23 |
Ajax(3) - CSV 형식 데이터 읽기, 검색 시 제시어 기능 (0) | 2019.10.23 |
JQuery 셋팅 및 예제 (10.18필기보고보완) (0) | 2019.10.23 |