앞에서 기술했던 부분에 이어 특정 게시판에 대한 관리 기능(게시글 목록 보기, 게시글 추가)을 기술한다. 다른 기능(게시글 수정, 게시글 삭제, 게시글 읽기)은 기술하지 않았다.
1. 게시글 목록 보기
- 헤더의 메뉴 중 "지식창고"에 마우스를 갖다대면 서브 메뉴가 나타난다. 이는 추가된 게시판에 대한 게시글 관리 기능으로의 링크이다. 이 링크를 누르면 해당 게시판에 대한 게시글 관리창으로 이동하게 된다.
예를 들어, "Web"이라는 서브 메뉴를 누르면 "http://localhost:8080/board/article/list?board_id=1"로 이동하게 된다.
1.1 ArticleController에서 /article/list에 대한 처리
package com.example.board.controller;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.example.board.domain.ArticleVO;
import com.example.board.domain.Criteria;
import com.example.board.domain.PageMaker;
import com.example.board.service.ArticleService;
import com.example.board.service.BoardService;
@Controller
@RequestMapping(value="/article")
public class ArticleController {
@Inject
public ArticleService service; // 게시글 관리 기능을 처리하기 위한 Service
@Inject
public BoardService bService; // 게시판 관리 기능을 처리하기 위한 Service
@RequestMapping(value="/list", method=RequestMethod.GET)
public void list(int board_id, Criteria cri, Model model) throws Exception {
model.addAttribute("board", bService.read(board_id)); // 해당 게시판에 대한 정보를 획득
model.addAttribute("list", service.list(cri)); // 해당 게시판의 게시글 목록 정보를 가져온다.
PageMaker pm = new PageMaker(); // 페이징 처리를 위한 인스턴스를 만든다.
pm.setCri(cri); // 페이징 처리를 위한 기준 정보를 저장
pm.setTotalCount(service.listCount()); // 해당 게시판의 전체 게시글의 수를 얻는다.
model.addAttribute("pageMaker", pm); // 페이징 처리를 위한 정보를 model에 저장
}
1.2 list.jsp : 게시글 목록 보기 화면
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게시글 목록 보기</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/common.css"/>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/boardlist.css"/>
</head>
<body>
<header> <!-- 헤더 영역 정의 -->
<jsp:include page="../common/header.jsp" flush="false"/>
</header>
<section id="wrap"> <!-- 본문 영역 정의 -->
<section id="lnav"> <!-- 사이드 메뉴 영역 정의 -->
<jsp:include page="../common/lnav.jsp" flush="false"/>
</section>
<section id="content"> <!-- 내용 영역 정의 -->
<h1>게시판 이름 : ${board.board_name}</h1>
<table>
<c:if test="${pageMaker.totalCount > 0}"><!-- 게시글이 있는지 검사 -->
<tr>
<td colspan="5"><!-- 페이지에 대한 정보를 표시 -->
${pageMaker.cri.pageStart}-${pageMaker.cri.pageEnd}
[${pageMaker.cri.page}/${pageMaker.totalPageCount}]
</td>
</tr>
</c:if>
<c:choose>
<c:when test="${list.size() == 0}"><!-- 게시글이 없을 때 안내문 표시 -->
<tr>
<td colspan="5">
게시글이 없습니다.
</td>
</tr>
</c:when>
<c:otherwise>
<tr><!-- 게시글에 대한 표시 타이틀 부분 -->
<td class="title_head" width="9%">번호</td>
<td class="title_head" width="54%">제목</td>
<td class="title_head" width="11%">작성자</td>
<td class="title_head" width="17%">작성일</td>
<td class="title_head" width="9%">조회수</td>
</tr>
<c:forEach var="article" items="${list}"><!-- 각 게시글에 대하여 -->
<tr>
<td>${article.article_id}</td>
<td width="40%">
<c:if test="${article.depth > 0}"><!-- 댓글에 대한 depth 표시 -->
<c:forEach begin="1" end="${article.depth}">-</c:forEach>>
</c:if>
<c:if test="${article.secret == 'T'}"><!-- 제목 처리 (비밀글 여부에 따라 다르게 처리)-->
<c:choose>
<c:when test="${sessionScope.member.category == 'admin'}">
<c:set var="query" value="article_id=${article.article_id}&page=${pageMaker.cri.page}
&perPageNum=${pageMaker.cri.perPageNum}"/>
<a href="<c:url value="/article/read?${query}"/>">${fn:substring(article.title, 0, 28)}</a>
</c:when>
<c:when test="${sessionScope.id == article.email}">
<c:set var="query" value="article_id=${article.article_id}&page=${pageMaker.cri.page}
&perPageNum=${pageMaker.cri.perPageNum}"/>
<a href="<c:url value="/article/read?${query}"/>">${fn:substring(article.title, 0, 28)}</a>
</c:when>
<c:otherwise>
${fn:substring(article.title, 0, 28)}
</c:otherwise>
</c:choose>
<img width="13px" height="13px" alt="*" src="<c:url
value="/resources/images/secret_image.png"/>">
</c:if>
<c:if test="${article.secret != 'T'}">
<c:choose>
<c:when test="${board.read_allow == 'all'}">
<c:set var="query" value="article_id=${article.article_id}&page=${pageMaker.cri.page}
&perPageNum=${pageMaker.cri.perPageNum}"/>
<a href="<c:url value="/article/read?${query}"/>">${fn:substring(article.title, 0, 28)}</a>
</c:when>
<c:when test="${board.read_allow == 'login' && sessionScope.id != null}">
<c:set var="query" value="article_id=${article.article_id}&page=${pageMaker.cri.page}
&perPageNum=${pageMaker.cri.perPageNum}"/>
<a href="<c:url value="/board/read?${query}"/>">${fn:substring(article.title, 0, 28)}</a>
</c:when>
<c:when test="${board.read_allow == 'login' && sessionScope.id == null}">
${fn:substring(article.title, 0, 28)}
</c:when>
<c:when test="${sessionScope.id != null && sessionScope.member.category ==
board.read_allow}">
<c:set var="query" value="article_id=${article.article_id}&page=${pageMaker.cri.page}
&perPageNum=${pageMaker.cri.perPageNum}"/>
<a href="<c:url value="/article/read?${query}"/>">${fn:substring(article.title, 0, 28)}</a>
</c:when>
<c:otherwise>
${fn:substring(article.title, 0, 28)}
</c:otherwise>
</c:choose>
</c:if>
</td>
<td>${article.writer_name}</td>
<td><fmt:formatDate value="${article.createdAt}" pattern="yyyy-MM-dd" /></td>
<td>${article.read_count}</td>
</tr>
<c:choose>
<c:when test="${board.display_format==2}"><!-- 본문의 표시 방법 처리 -->
<tr>
<td colspan="5">${fn:substring(article.content, 0, 200)}</td>
</tr>
</c:when>
<c:when test="${board.display_format==3}">
<tr>
<td colspan="5">${article.content}</td>
</tr>
</c:when>
</c:choose>
</c:forEach>
<tr>
<td colspan="5"><!-- 페이징 처리(링크 표시) -->
<c:if test="${pageMaker.prev == true}">
<a href="<c:url value="/article/list?board_id=${board.board_id}&page=
${pageMaker.startPage-1}&perPageNum=${pageMaker.cri.perPageNum}"/>">이전</a>
</c:if>
<c:forEach var="pno" begin="${pageMaker.startPage}" end="${pageMaker.endPage}">
<a href="<c:url value="/article/list?board_id=${board.board_id}&page=${pno}
&perPageNum=${pageMaker.cri.perPageNum}" />">[${pno}]</a>
</c:forEach>
<c:if test="${pageMaker.next == true}">
<a href="<c:url value="/article/list?board_id=${board.board_id}&page=
${pageMaker.endPage+1}&perPageNum=${pageMaker.cri.perPageNum}"/>">다음</a>
</c:if>
</td>
</tr>
</c:otherwise>
</c:choose>
<c:choose><!-- 글쓰기 권한에 따른 글쓰기 허용여부 처리 -->
<c:when test="${board.write_allow == 'all'}">
<tr>
<td colspan="5"><a href="write?board_id=${board.board_id}">글쓰기</a></td>
</tr>
</c:when>
<c:when test="${board.write_allow == 'login' && sessionScope.id != null}">
<tr>
<td colspan="5"><a href="write?board_id=${board.board_id}">글쓰기</a></td>
</tr>
</c:when>
<c:when test="${sessionScope.id != null && sessionScope.member.category ==
board.write_allow}">
<tr>
<td colspan="5"><a href="write?board_id=${board.board_id}">글쓰기</a></td>
</tr>
</c:when>
</c:choose>
</table>
</section>
</section>
<footer> <!-- 풋터 영역 정의 -->
<jsp:include page="../common/footer.jsp" flush="false"/>
</footer>
</body>
</html>
게시글 쓰기 링크를 누르면 게시글 쓰기로 이동한다. (/article/write)
1.3 ArticleController /article/write 처리
@RequestMapping(value="write", method=RequestMethod.GET)
public String write(int board_id, Model model) {
model.addAttribute("board", bService.read(board_id)); // 해당 게시판에 대한 정보를 획득
return "/article/writeForm"; // 게시글 입력 창으로 이동
}
1.4 writeForm.jsp : 게시글 입력 폼 화면
위 그림과 같이 게시글 쓰기 입력 창을 보여준다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>게시글 쓰기</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/common.css"/>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/articlewrite.css"/>
<script type="text/javascript" src="<c:url value="/resources/js/jquery-1.11.3.min.js"/>"></script>
<script type="text/javascript" charset="utf-8" src="<c:url value="/resources/js/articlewrite.js"/>"></script>
</head>
<body>
<c:choose>
<c:when test="${param.article_id != null}">
<c:set var="num" value="${param.article_id}"/>
<c:set var="ref" value="${param.ref}"/>
<c:set var="step" value="${param.step}"/>
<c:set var="depth" value="${param.depth}"/>
</c:when>
<c:otherwise>
<c:set var="num" value="0"/>
<c:set var="ref" value="1"/>
<c:set var="step" value="0"/>
<c:set var="depth" value="0"/>
</c:otherwise>
</c:choose>
<header> <!-- 헤더 영역 정의 -->
<jsp:include page="../common/header.jsp" flush="false"/>
</header>
<section id="wrap"> <!-- 본문 영역 정의 -->
<section id="lnav"> <!-- 사이드 메뉴 영역 정의 -->
<jsp:include page="../common/lnav.jsp" flush="false"/>
</section>
<section id="content"> <!-- 내용 영역 정의 -->
<c:if test="${num == 0}">
<h2>게시글 작성</h2>
</c:if>
<c:if test="${num != 0}">
<h2>댓글 작성</h2>
</c:if>
<form action="<c:url value='write' />" method="post" id="frm">
<input type="hidden" name="board_id" value="${param.board_id}">
<input type="hidden" name="num" value="${num}">
<input type="hidden" name="ref" value="${ref}">
<input type="hidden" name="step" value="${step}">
<input type="hidden" name="depth" value="${depth}">
<input type="hidden" name="author" value="">
<table>
<tr>
<td>제목: </td>
<td>
<c:if test="${num == 0}">
<input type="text" name="title" size="90" maxlength="60" placeholder="제목을 입력 하십시
요." required/>
</c:if>
<c:if test="${num != 0}">
<input type="text" name="title" size="90" maxlength="60" value="[답변]"/>
</c:if>
</td>
</tr>
<c:if test="${sessionScope.id != null}">
<tr>
<td>작성자: </td>
<td><label>${sessionScope.member.nickname}</label></td>
</tr>
<input type="hidden" name="writer_name" value="${sessionScope.member.nickname}"/>
<input type="hidden" name="email" value="${sessionScope.member.id}">
<input type="hidden" name="password" value="${sessionScope.member.password}"/>
</c:if>
<c:if test="${sessionScope.id == null}">
<tr>
<td>작성자: </td>
<td><input type="text" name="writer_name" /></td>
</tr>
<input type="hidden" name="email" value="이메일">
<tr>
<td>글암호: </td>
<td><input type="password" name="password" /></td>
</tr>
</c:if>
<tr>
<td style="margin:0; padding:0;" colspan="2"><textarea name="content" rows="5" cols="80"
style="width:100%; height:212px;"></textarea></td>
</tr>
</table>
<input id="addBtn" type="submit" value="전송" />
</form>
</section>
</section>
<footer> <!-- 풋터 영역 정의 -->
<jsp:include page="../common/footer.jsp" flush="false"/>
</footer>
</body>
</html>
1.5 articlewrite.js : 첨부 파일을 5개 까지 추가할 수 있도록 dynamic하게 파일 첨부 버튼을 조작
생략
[마치며] 처음에는 잘 정리해야 겠다고 생각을 했는데, 내용이 방대하여 마음의 여유가 없어지고, 조급해져 일부 내용을 빠트리고 정리가 된 것 같다. 글쎄 다른 사람이 이글을 보고 이해할 수 있을지 염려도 되지만 source code를 추가로 첨부해 본다.
'웹개발' 카테고리의 다른 글
스프링에서 REST API 제공방법 (1/2) (0) | 2017.03.10 |
---|---|
정규 표현식에 대한 공부 (0) | 2017.03.09 |
게시판 관리기능 - 여러 개의 게시판이 필요할 때 (4/5) (0) | 2017.03.08 |
Oracle 11g에서 sequence 초기값 1 고려사항 (0) | 2017.03.08 |
게시판 관리기능 : 여러 개의 게시판이 필요할 때 (3/5) (0) | 2017.03.07 |