Dev/Struts

Struts2/Spring2.5/iBatis/Ajax - 댓글 기능을 제공하는 게시판 만들기

창문닦이 2019. 4. 4. 18:17

개발환경셋팅

- JRE 7.x 
- Eclipse 
- Oracle 
- Tomcat 7.x

[구조]

com.util.sqlMap

ibbs_sqlMap.xml < 2개의 테이블에 해당하는 sql문이 모두 들어가도 됨


com.ibbs

BoardAction.java (게시물)

BoardDTO.java (게시물)

CommentAction.java (댓글)

CommentDTO.java (댓글)


WebContent

 ibbs

    css

article.css

created.css

list.css

          commentStyle.css

          style.css

    article.jsp

    commentList.jsp (방명록의 list에 해당하는 부분)

    created.jsp

    list.jsp


WEB-INF

 classes

    struts.xml

    struts-ibbs.xml


 sqlMapConfig

    sqlMapConfig.xml

1. 테이블 생성

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

);

2. IBATIS 셋팅

<sqlMap resource="com/util/sqlMap/ibbs_sqlMap.xml"/>

ibbs_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="ibbs">

<!-- 댓글 -->

<select id="numMaxComment" parameterClass="int" resultClass="int">

select nvl(max(commentNum),0) from ibbscomment

</select>

<select id="countComment" parameterClass="int" resultClass="int">

select count(*) from ibbscomment where boardNum = #boardNum#

</select>

<insert id="insertComment" parameterClass="com.ibbs.CommentDTO">

insert into ibbscomment (boardNum,commentNum, name, content, ipAddr, created)

values(#boardNum#,#commentNum#,#name#, #content#,#ipAddr#,sysdate)

</insert>

<select id="listComment" parameterClass="map" resultClass="com.ibbs.CommentDTO">

select * from(

select rownum rnum, data.* from(

select boardNum, commentNum, name, content, ipAddr, created

from ibbscomment

where boardNum=#boardNum#

order by commentNum desc ) data )

<![CDATA[

where rnum>=#start# and rnum<=#end#

]]>

</select>

<delete id="deleteComment" parameterClass="map">

delete ibbscomment where commentNum=#commentNum# and boardNum=#boardNum#

</delete>

<!-- 게시물 -->

<select id="numMax" resultClass="int">

select nvl(max(boardNum),0) from ibbs

</select>

<insert id="insertData" parameterClass="com.ibbs.BoardDTO">

insert into ibbs(boardNum,name,subject,email,content,pwd,ipAddr,hitcount,created)

values(#boardNum#,#name#,#subject#,#email#,#content#,#pwd#,#ipAddr#,0,sysdate)

</insert>

<select id="dataCount" parameterClass="map" resultClass="int">

select nvl(count(*),0) from ibbs

where $searchKey$ like '%' || #searchValue# || '%'

</select>

<select id="listData" parameterClass="map" resultClass="com.ibbs.BoardDTO">

select * from (

select rownum rnum,data.* from(

select boardNum,name,subject,email,hitCount,

to_char(created,'YYYY-MM-DD') created from ibbs

where $searchKey$ like '%' || #searchValue# || '%'

order by boardNum desc) data)

<![CDATA[

where rnum>=#start# and rnum<=#end#

]]>

</select>

<select id="readData" resultClass="com.ibbs.BoardDTO" parameterClass="int">

select boardNum,name,pwd,email,subject,content,ipAddr,hitCount,

created from ibbs where boardNum=#boardNum#

</select>

<select id="preReadData" resultClass="com.ibbs.BoardDTO" parameterClass="map">

select rownum rnum,data.* from(

select boardNum,subject from ibbs

where($searchKey$ like '%'||#searchValue#||'%')

<![CDATA[

and (boardNum>#boardNum#) order by boardNum asc) data

where rownum=1

]]>

</select>

<select id="nextReadData" resultClass="com.ibbs.BoardDTO" parameterClass="map">

select rownum rnum,data.* from(

select boardNum,subject from ibbs

where($searchKey$ like '%'||#searchValue#||'%')

<![CDATA[

and (boardNum<#boardNum#) order by boardNum desc) data

where rownum=1

]]>

</select>

<update id="updateHitCount" parameterClass="int">

update ibbs set hitCount=hitCount+1 where boardNum=#boardNum#

</update>

<update id="updateData" parameterClass="com.ibbs.BoardDTO">

update ibbs set name=#name#,pwd=#pwd#,email=#email#,

subject=#subject#,content=#content# where boardNum=#boardNum#

</update>

<delete id="deleteData" parameterClass="int">

delete ibbs where boardNum=#boardNum#

</delete>

</sqlMap>

3. STRUTS 셋팅

<include file="struts-ibbs.xml"/>

struts-ibbs.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="ibbs" extends="default" namespace="/ibbs" >       

<!-- 게시글 작성 -->

<action name="created" class="com.ibbs.BoardAction" method="created">

<interceptor-ref name="myPrepareParamsStack"></interceptor-ref>

<result name="input">/ibbs/created.jsp</result>

<result name="success" type="redirectAction">list</result>

</action>

<!-- 게시판 조회 -->

<action name="list" class="com.ibbs.BoardAction" method="list">

<result name="success">/ibbs/list.jsp</result>

</action>

<!-- 게시글 조회 -->

<action name="article" class="com.ibbs.BoardAction" method="article">

<result name="success">/ibbs/article.jsp</result>

<result name="read-error" type="redirectAction">list</result>

</action>

<!-- 게시글 수정 -->

<action name="updated" class="com.ibbs.BoardAction" method="updated">

<interceptor-ref name="myPrepareParamsStack"></interceptor-ref>

<result name="input">/ibbs/created.jsp</result>

<result name="success" type="redirectAction">list?pageNum=${pageNum}&amp;searchKey=${searchKey}&amp;searchValue=${searchValue}</result>

</action>

<!-- 게시글 삭제 -->

<action name="deleted" class="com.ibbs.BoardAction" method="deleted">

<interceptor-ref name="myPrepareParamsStack"></interceptor-ref>

<result name="success" type="redirectAction">list</result>

</action>

</package>

<package name="ibbsguest" extends="default" namespace="/ibbsguest" >       

<!-- 댓글작성 -->

<action name="created" method="created" class="com.ibbs.CommentAction">

<interceptor-ref name="myPrepareParamsStack"/>

<result>/ibbs/commentList.jsp</result>

</action>

<!-- 댓글리스트 -->

<action name="list" method="list" class="com.ibbs.CommentAction">

<result>/ibbs/commentList.jsp</result>

</action>

<!-- 댓글삭제 -->

<action name="deleted" method="deleted" class="com.ibbs.CommentAction">

<result>/ibbs/commentList.jsp</result>

</action>

</package>

</struts>

5. DTO 클래스 

package com.ibbs;

public class BoardDTO {

private int listNum;

private int commentCount;

private String mode;

private String pageNum;

private String searchKey;

private String searchValue;


//DB 데이터

private int boardNum;

private String name;

private String subject;

private String email;

private String content;

private String pwd;

private String ipAddr;

private String created;

private int hitCount;

GETTER, SETTER 작성

}


package com.ibbs;

public class CommentDTO {

private int listNum;

private String pageNum;

//DB 데이터

private int commentNum;

private int boardNum;

private String name;

private String content;

private String ipAddr;

private String created;

GETTER, SETTER 작성

}

6. Action 클래스

BoardAction

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 BoardDTO dto;

private static final long serialVersionUID = 1L;

@Resource(name="dao")

private CommonDAO 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();

String pageNum = dto.getPageNum();

String searchKey = dto.getSearchKey();

String searchValue = dto.getSearchValue();

if(searchValue==null){

searchKey = "subject";

searchValue = "";

}

//페이지 유지 위해 검색값 전달

String params= "pageNum=" + pageNum;

if(!searchValue.equals("")){

searchValue = URLEncoder.encode(searchValue, "UTF-8");

params += "&searchKey="+searchKey+"&searchValue="+searchValue;

}

request.setAttribute("params", params);

if(dto==null||dto.getMode()==null||dto.getMode().equals("")){

request.setAttribute("mode", "created");

return INPUT;

}

int numMax= dao.getIntValue("ibbs.numMax");

dto.setBoardNum(numMax+1);

dto.setIpAddr(request.getRemoteAddr());

dao.insertData("ibbs.insertData", dto);

return SUCCESS;

}

//게시글 리스트

public String list() throws Exception{

HttpServletRequest request = ServletActionContext.getRequest();

String cp = request.getContextPath();

int numPerPage = 10;

int totalPage = 0;

int totalDataCount = 0;

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

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

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

int currentPage = 1;

if(pageNum!=null)

currentPage = Integer.parseInt(pageNum);

if(searchValue==null){

searchKey = "subject";

searchValue = "";

}

if(request.getMethod().equalsIgnoreCase("GET"))

searchValue = URLDecoder.decode(searchValue,"UTF-8");

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;

Iterator<Object> it = lists.iterator();

while(it.hasNext()){

BoardDTO vo = (BoardDTO)it.next();

listNum = totalDataCount - (start+n-1);

vo.setListNum(listNum);

vo.setCommentCount((Integer)dao.getReadData("ibbs.countComment", vo.getBoardNum()));

n++;

}

//하이퍼링크 주소정리

String params = "";

String urlArticle = "";

String urlList ="";

if(!searchValue.equals("")){

//검색단어 있을경우 인코딩 후 주소어 붙여줌

searchValue = URLEncoder.encode(searchValue, "UTF-8");

params += "searchKey="+searchKey+"&searchValue="+searchValue;

}

urlList = cp + "/ibbs/list.action";

urlArticle = cp + "/ibbs/article.action?pageNum="+currentPage;

if(!params.equals("")){

urlList += "?"+params;

urlArticle +="&" + params;

}

request.setAttribute("lists",lists);

request.setAttribute("totalDataCount", totalDataCount);

request.setAttribute("urlArticle", urlArticle);

request.setAttribute("pageNum", pageNum);

request.setAttribute("currentPage", currentPage);

request.setAttribute("params", params);

request.setAttribute("pageIndexList", myUtil.pageIndexList(currentPage, totalPage, urlList));

return SUCCESS;

}

//게시물조회

public String article() throws Exception{

HttpServletRequest request = ServletActionContext.getRequest();

int boardNum = Integer.parseInt(request.getParameter("boardNum"));

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

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

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

if(searchValue==null){

searchKey = "subject";

searchValue = "";

}

if(request.getMethod().equalsIgnoreCase("GET"))

searchValue = URLDecoder.decode(searchValue,"UTF-8");

dao.updateData("ibbs.updateHitCount", boardNum);//조회수증가

dto = (BoardDTO)dao.getReadData("ibbs.readData",boardNum);

if(dto==null)

return "read-error";

int lineSu = dto.getContent().split("\r\n").length;

dto.setContent(dto.getContent().replaceAll("\r\n", "<br/>"));//줄바꿈

Map<String,Object> hMap = new HashMap<String, Object>();

hMap.put("searchKey", searchKey);

hMap.put("searchValue", searchValue);

hMap.put("boardNum", dto.getBoardNum());

//이전글

BoardDTO preDTO = (BoardDTO)dao.getReadData("ibbs.preReadData",hMap);

int preNum = 0;

String preSubject = "";

if(preDTO!=null){

preNum = preDTO.getBoardNum();

preSubject =preDTO.getSubject();

}

//다음글

BoardDTO nextDTO = (BoardDTO)dao.getReadData("ibbs.nextReadData",hMap);

int nextNum = 0;

String nextSubject = "";

if(nextDTO!=null){

nextNum = nextDTO.getBoardNum();

nextSubject =nextDTO.getSubject();

}

//페이지 유지 위해 검색값 전달

String params= "pageNum=" + pageNum;

if(!searchValue.equals("")){

searchValue = URLEncoder.encode(searchValue, "UTF-8");

params += "&searchKey="+searchKey+"&searchValue="+searchValue;

}

//getter를 안만들어줘서 수동으로 dto를 전송해야한다.

request.setAttribute("dto", dto);

request.setAttribute("pageNum", pageNum);

request.setAttribute("preNum", preNum);

request.setAttribute("preSubject", preSubject);

request.setAttribute("nextNum", nextNum);

request.setAttribute("nextSubject", nextSubject);

request.setAttribute("searchKey", searchKey);

request.setAttribute("searchValue", searchValue);

request.setAttribute("params", params);

request.setAttribute("lineSu", lineSu);

return SUCCESS;

}

//게시물수정

public String updated() throws Exception{

HttpServletRequest request = ServletActionContext.getRequest();

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

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

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

//검색값 없을 경우

if(searchValue==null){

searchKey = "subject";

searchValue = "";

}

//검색값 있을 경우 한글디코딩

if(request.getMethod().equalsIgnoreCase("GET")){

searchValue = URLDecoder.decode(searchValue, "UTF-8");

}

//페이지 유지 위해 검색값 전달

String params= "pageNum=" + pageNum;

if(!searchValue.equals("")){

searchValue = URLEncoder.encode(searchValue, "UTF-8");//g한글때문에 인코딩

params += "&searchKey="+searchKey+"&searchValue="+searchValue;

}

request.setAttribute("params", params);

request.setAttribute("searchKey", searchKey);

request.setAttribute("searchValue", searchValue);

//수정입력창

if(dto==null||dto.getMode()==null||dto.getMode().equals("")){

dto = (BoardDTO)dao.getReadData("ibbs.readData",dto.getBoardNum());

if(dto==null)

return "read-error";

request.setAttribute("pageNum", pageNum);

request.setAttribute("mode", "updated");

request.setAttribute("dto", dto);

return INPUT;

}

//수정반영

dao.updateData("ibbs.updateData", dto);

request.setAttribute("pageNum", pageNum);

return SUCCESS;

}

//게시물삭제

public String deleted() throws Exception{

HttpServletRequest request = ServletActionContext.getRequest();

int boardNum = Integer.parseInt(request.getParameter("boardNum"));

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

String searchKey = dto.getSearchKey();

String searchValue = dto.getSearchValue();

if(searchValue==null){

searchKey = "subject";

searchValue = "";

}

//페이지 유지 위해 검색값 전달

String params= "pageNum=" + pageNum;

if(!searchValue.equals("")){

searchValue = URLEncoder.encode(searchValue, "UTF-8");

params += "searchKey="+searchKey+"&searchValue="+searchValue;

}

dto.setPageNum(pageNum);

dao.deleteData("ibbs.deleteData",boardNum);

request.setAttribute("pageNum", pageNum);

request.setAttribute("params", params);

request.setAttribute("searchKey", searchKey);

request.setAttribute("searchValue", searchValue);

return SUCCESS;

}

}

CommentAction

package com.ibbs;

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 CommentAction extends ActionSupport

implements Preparable, ModelDriven<CommentDTO>{

private static final long serialVersionUID = 1L;

private CommentDTO dto;

/*

Ajax가 데이터를 넘김으로 Getter는 불필요함

public CommentDTO getDto() {

return dto;

}

*/

@Resource(name="dao")

private CommonDAO dao;

@Resource(name="myUtil")

private MyUtil myUtil;

@Override

public CommentDTO getModel() {

return dto;

}

@Override

public void prepare() throws Exception {

dto = new CommentDTO();

}

//댓글 입력

public String created() throws Exception {

HttpServletRequest request = ServletActionContext.getRequest();

int boardNum = Integer.parseInt(request.getParameter("boardNum"));

int maxNum = dao.getIntValue("ibbs.numMaxComment");

dto.setBoardNum(boardNum);

dto.setCommentNum(maxNum+1);//게시물번호

dto.setIpAddr(request.getRemoteAddr());

dao.insertData("ibbs.insertComment", 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 boardNum = Integer.parseInt(request.getParameter("boardNum"));

int currentPage = 1;

if(pageNum!=null&&pageNum!=""){

currentPage = Integer.parseInt(pageNum);

}else{

pageNum = "1";

}

totalDataCount = dao.getIntValue("ibbs.countComment",boardNum);

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("boardNum", boardNum);

hMap.put("start",start);

hMap.put("end", end);

List<Object> lists = (List<Object>)dao.getListData("ibbs.listComment",hMap);

int listNum,n=0;

Iterator<Object> it = lists.iterator();

while(it.hasNext()){

CommentDTO vo = (CommentDTO)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 commentNum = Integer.parseInt(request.getParameter("commentNum"));

int boardNum = Integer.parseInt(request.getParameter("boardNum"));

Map<String,Object> hMap = new HashMap<String,Object>();

hMap.put("commentNum",commentNum);

hMap.put("boardNum", boardNum);

dao.deleteData("ibbs.deleteComment",hMap);

//redirect하지 않고 list로 연동

return list();

}

}

7.1 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 %>/ibbs/css/style.css" type="text/css" />

<link rel="stylesheet" href="<%=cp %>/ibbs/css/list.css" type="text/css" />

<script type="text/javascript">

function searchData(){

var f = document.searchForm;

f.action = "<%=cp%>/ibbs/list.action";

f.submit();

}

</script>

</head>

<body>

<div id="bbsList">

<div id="bbsList_title">

게 시 판(Struts2+Spring2.5+Ajax)

</div>

<div id="bbsList_header">

<div id="leftHeader">

<form action="" name="searchForm" method="post">

<select name="searchKey" class="selectField">

<option value="subject">제목</option>

<option value="name">작성자</option>

<option value="content">내용</option>

</select>

<input type="text" name="searchValue" class="textField"/>

<input type="button" value="검  색" class="btn2" onclick="searchData();"/>

</form>

</div>

<div id="rightHeader">

<input type="button" value=" 글올리기 " class="btn2"

onclick="javascript:location.href='<%=cp %>/ibbs/created.action?pageNum=${currentPage}&${params }';"/>

</div>

</div>

<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 }

<c:if test="${dto.commentCount!=0 }">[${dto.commentCount }]</c:if></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>

</div>

</body>

</html>

7.2 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 %>/ibbs/css/style.css" type="text/css" />

<link rel="stylesheet" href="<%=cp %>/ibbs/css/created.css" type="text/css" />

<script type="text/javascript" src="<%=cp %>/ibbs/js/util.js"></script>

<script type="text/javascript" >

function sendIt(){

f = document.myForm;

str = f.subject.value;

str = str.trim();//util.js에 있는 trim함수 호출

if(!str){

alert("\n제목을 입력하세요.");//공백제거후 내용이 없으면

f.subject.focus();

return;

}

f.subject.value = str;

str = f.name.value;

str = str.trim();

if(!str){

alert("\n이름을 입력하세요.");

f.name.focus();

return;

}

f.name.value = str;

/*

//이름 한글검사

if(!isValidKorean(str)){

alert("\n이름을 정확히 입력하세요.");

f.name.focus();

return;

}

*/

if(f.email.value){

if(!isValidEmail(f.email.value)){

alert("\n정상적인 E-mail을 입력하세요");

f.email.focus();

return;

}

}

str = f.content.value;

str = str.trim();

if(!str){

alert("\n내용을 입력하세요.");

f.content.focus();

return;

}

f.content.value = str;

str = f.pwd.value;

str = str.trim();

if(!str){

alert("\n패스워드를 입력하세요.");

f.pwd.focus();

return;

}

f.pwd.value = str;

if(f.mode.value=="created"){

f.action = "<%=cp%>/ibbs/created.action";

}else if(f.mode.value=="updated"){

f.action = "<%=cp%>/ibbs/updated.action";

}

f.submit();

}

</script>

</head>

<body>

<div id="bbs" >

<div id="bbs_title">

게 시 판(Struts2+Spring2.5+Ajax)

</div>

<form action="" name="myForm" method="post">

<div id="bbsCreated">

<div class="bbsCreated_bottomLine">

<dl>

<dt>제&nbsp;&nbsp;&nbsp;&nbsp;목</dt>

<dd>

<input type="text" name="subject" value="${dto.subject}" size="74" maxlength="100" class="boxTF"/>

</dd>

</dl>

</div>

<div class="bbsCreated_bottomLine">

<dl>

<dt>작성자</dt>

<dd>

<input type="text" name="name" value="${dto.name }" size="35" maxlength="20" class="boxTF"/>

</dd>

</dl>

</div>

<div class="bbsCreated_bottomLine">

<dl>

<dt>E-Mail</dt>

<dd>

<input type="text" name="email" value="${dto.email }" size="35" maxlength="50" class="boxTF"/>

</dd>

</dl>

</div>

<div id="bbsCreated_content">

<dl>

<dt>내&nbsp;&nbsp;&nbsp;&nbsp;용</dt>

<dd>

<textarea rows="12" cols="63" name="content" class="boxTA">${dto.content }</textarea>

</dd>

</dl>

</div>

<div class="bbsCreated_noLine">

<dl>

<dt>패스워드</dt>

<dd>

<input type="password" name="pwd" value="${dto.pwd }" size="35" maxlength="7" class="boxTF"/>

&nbsp;(게시물 수정 및 삭제시 필요)

</dd>

</dl>

</div>

</div>

<div id="bbsCreated_footer">S

<!-- 검색페이지 유지시 필요한 파라미터 -->

<input type="hidden" name="searchKey" value="${searchKey}"/>

<input type="hidden" name="searchValue" value="${searchValue}"/>

<!-- 작성/수정 구분 파라미터 -->

<input type="hidden" name="mode" value="${mode}"/>

<input type="hidden" name="boardNum" value="${dto.boardNum}"/>

<input type="hidden" name="pageNum" value="${pageNum}"/>

<c:if test="${mode=='created' }">

<input type="button" value="등록하기" class="btn2"

onclick="sendIt();" />

<input type="reset" value="다시입력" class="btn2"

onclick="document.myForm.subject();" />

<input type="button" value="작성취소" class="btn2"

onclick="javascript:location.href='<%=cp %>/ibbs/list.action?${params}';" />

</c:if>

<c:if test="${mode=='updated' }">

<input type="button" value="수정하기" class="btn2" onclick="sendIt();" />

<input type="button" value="수정취소" class="btn2"

onclick="javascript:location.href='<%=cp %>/ibbs/list.action?${params}';" />

</c:if>

</div>

</form>

</div>

</body>

</html>

7.3 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 %>/ibbs/css/style.css" type="text/css" />

<link rel="stylesheet" href="<%=cp%>/ibbs/css/commentStyle.css" type="text/css">

<link rel="stylesheet" href="<%=cp %>/ibbs/css/article.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() +

"&boardNum=" + $("#boardNum").val() +

"&content=" + $("#content").val();

$.ajax({

type:"POST",

url:"<%=cp%>/ibbsguest/created.action",

data:params,

success:function(args){

//넘어온값이 args에 담겨있음

$("#listData").html(args);

//초기화

$("#name").val("");

$("#content").val("");

$("#name").focus();

},

beforeSend:showRequest,

error:function(e){

alert(e.responseText);

}

});

});

});

function showRequest(){

//beforesend 보내기전에 실행되는 함수

var name = $.trim($("#name").val());//Ajax에서 제공하는 trim함수

var content = $.trim($("#content").val());

var boardNum = $.trim($("#boardNum").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;//진행 중단

}

if(!boardNum){

alert(boardNum+"게시물이 존재하지 않습니다.");

return false;//진행 중단

}

return true;

}

function listPage(page){

var url = "<%=cp%>/ibbsguest/list.action";

var boardNum = $("#boardNum").val();

$.post(url,{boardNum:boardNum,pageNum:page},function(args){

$("#listData").html(args);

});

$("#listData").show();//display:block

}

function deleteComment(boardNum,commentNum,page){

//삭제 후 페이지 이동 필요

var url = "<%=cp%>/ibbsguest/deleted.action";

$.post(url,{boardNum:boardNum,commentNum:commentNum,pageNum:page},function(args){

$("#listData").html(args);

});

}

</script>

<script type="text/javascript">

function updateData(){

var boardNum = "${dto.boardNum}";

var param = "boardNum="+boardNum;

var url = "<%=cp%>/ibbs/updated.action?"+param+"&${params}";

location.replace(url);

}

function deleteData(){

var boardNum = "${dto.boardNum}";

var param = "boardNum="+boardNum;

var url = "<%=cp%>/ibbs/deleted.action?"+param+"&${params}";

location.replace(url);

}

</script>

</head>

<body>

<div id="bbs">

<div id="bbs_title">

게 시 판(Struts2+Spring2.5+Ajax)

</div>

<div id="bbsArticle">

<div id="bbsArticle_header">

${dto.subject }

</div>

<div class="bbsArticle_bottomLine">

<dl>

<dt>작성자</dt>

<dd>${dto.name }

<c:if test="${!empty dto.email }">

(<a href="mailto:${dto.email }">${dto.email }</a>)

</c:if>

</dd>

<dt>줄수</dt>

<dd>${lineSu }</dd>

</dl>

</div>

<div class="bbsArticle_bottomLine">

<dl>

<dt>등록일</dt>

<dd>${dto.created }</dd>

<dt>조회수</dt>

<dd>${dto.hitCount }</dd>

</dl>

</div>

<div id="bbsArticle_content">

<table width="600" border="0">

<tr>

<td style="padding: 20px 80px 20px 62px;" valign="top" height="200">

${dto.content }

</td>

</tr>

</table>

</div>

<div class="bbsArticle_bottomLine">

이전글:

<c:if test="${!empty preSubject }">

<a href="<%=cp%>/bbs/article.action?${params}&boardNum=${preNum}">${preSubject }</a>

</c:if>

</div>

<div class="bbsArticle_bottomLine">

다음글:

<c:if test="${!empty nextSubject }">

<a href="<%=cp%>/bbs/article.action?${params}&boardNum=${nextNum}">${nextSubject }</a>

</c:if>

</div>

</div>

<div class="bbsArticle_noLine" style="text-align: right;">

from ${dto.ipAddr }

</div>

<div id="bbsArticle_footer">

<div id="leftFooter">

<input type="hidden" value="${pageNum }" name="pageNum">

<input type="hidden" value="${dto.boardNum }" name="boardNum" id="boardNum">

<input type="hidden" value="${params }" name="params">

<input type="hidden" value="${searchKey }" name="searchKey">

<input type="hidden" value="${searchValue }" name="searchValue">

<input type="button" value=" 수정 " class="btn2" onclick="updateData();" />

<input type="button" value=" 삭제 " class="btn2" onclick="deleteData();" />

</div>

<div id="rightFooter">

<input type="button" value=" 리스트 " class="btn2"

onclick="javascript:location.href='<%=cp %>/ibbs/list.action?${params }';" />

</div>

</div>

</div>

<div id="bbs">

<span id="listData" style="display: none;"></span>

<table width="600" border="1" cellpadding="0" cellspacing="0" bordercolor="#e6d4a6" align="center">

<tr height="25">

<td style="padding-left: 20px;"><b>댓글 작성</b></td>

</tr>

</table>

<table width="600" border="0" cellpadding="0" cellspacing="0" align="center">

<tr>

<td width="600" colspan="4" height="2" bgcolor="#e6d4a6"></td>

</tr>

<tr>

<td width="60" height="30" bgcolor="#eeeeee" align="center">작성자</td>

<td width="500" height="30" style="padding-left: 10px;" colspan="2">

<input type="text" id="name" size="72" maxlength="20" class="boxTF">

</td>

<td width="40" height="30" style="padding-left: 6px;" rowspan="3">

<input type="button" value="댓글 등록" id="sendButton" style="height:75pt;" class="btn2" />

</td>

</tr>

<tr><td width="600" colspan="3" height="1" bgcolor="#e6d4a6"></td></tr>

<tr height="30">

<td width="60" height="30" bgcolor="#eeeeee" align="center">내용</td>

<td width="500" colspan="2" style="padding-left: 10px;">

<textarea id="content" rows="3" cols="70" class="boxTA"></textarea>

</td>

</tr>

<tr><td width="600" colspan="4" height="1" bgcolor="#e6d4a6"></td></tr>

</table>

</div>

</body>

</html>

7.2 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();

%>

<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" bgcolor="#999999" height="1"></td>

</tr>

<tr height="30" bgcolor="#dbdbdb">

<td width="300" style="padding-left: 10px;">

<b>No ${dto.listNum }.${dto.name }</b>

</td>

<td width="300" align="right" style="padding-right: 10px;">

${dto.created }&nbsp;

<a href="javascript:deleteComment('${dto.boardNum }','${dto.commentNum }','${pageNum }')">삭제</a>

</td>

</tr>

<tr>

<td height="30" style="padding-left: 10px;" colspan="2">

${dto.content }

</td>

</tr>

</c:forEach>

<tr>

<td colspan="2" bgcolor="#dbdbdb" height="2"></td>

</tr>

<tr height="30">

<td align="center" colspan="2">

${pageIndexList }

</td>

</tr>

</table>

</c:if>

실행 화면