BACK-END/SPRING
[SPRING] MVC 게시판
진심스테이크
2019. 9. 25. 16:00
DAO : 데이터 베이스 연동
Mapper : Query문
DTO : 모델
Service : 비즈니스 로직
Controller
Views : JSP
구조
BoardController.java
package com.project.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.board.db.BoardDTO;
import com.board.service.BoardService;
import com.board.service.Criteria;
import com.board.service.Paging;
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowired
private BoardService service;
// 게시판 목록
@RequestMapping("/list")
public String boardList(BoardDTO dto, Model model, Criteria cri) throws Exception {
Paging paging = new Paging();
paging.setCri(cri);
paging.setTotalCount(service.boardListCnt(dto));
int pageNum = paging.getCri().getPage();
List<Map<String, Object>> list = service.listAll(cri);
model.addAttribute("boardList", list);
model.addAttribute("pageNum", pageNum);
model.addAttribute("paging", paging);
return "/board/BoardList";
}
// 글 읽기
@RequestMapping("/detail")
public ModelAndView boardDetail(@RequestParam int no) throws Exception {
service.boardHit(no);
ModelAndView mav = new ModelAndView();
mav.setViewName("/board/BoardDetail");
mav.addObject("boardDetail", service.boardDetail(no));
return mav;
}
// 글 삭제
@RequestMapping("/delete")
public String boardDelete(@RequestParam int no) throws Exception {
service.boardDelete(no);
return "redirect:/board/list";
}
// 글 작성 페이지
@RequestMapping("/writePage")
public String boardWritePage() {
return "/board/BoardWrite";
}
// 글 작성
@RequestMapping("/write")
public String boardWrite(@ModelAttribute BoardDTO dto) throws Exception {
service.boardWrite(dto);
return "redirect:/board/list";
}
// 글 수정 페이지
@RequestMapping("/editPage")
public ModelAndView boardEditPage(@RequestParam int no) throws Exception {
ModelAndView mav = new ModelAndView();
mav.setViewName("/board/BoardEdit");
mav.addObject("boardEdit", service.boardDetail(no));
return mav;
}
// 글 수정
@RequestMapping("/edit")
public String boardEdit(@ModelAttribute BoardDTO dto) throws Exception {
service.boardEdit(dto);
return "redirect:/board/detail?no=" + dto.getNo();
}
}
BoardService.java / BoardServiceImpl.java
package com.board.service;
import java.util.List;
import java.util.Map;
import com.board.db.BoardDTO;
public interface BoardService {
// 게시판 목록
public List<BoardDTO> boardList() throws Exception;
// 글 읽기
public BoardDTO boardDetail(int no) throws Exception;
// 글 조회수
public void boardHit(int no) throws Exception;
//글 삭제
public void boardDelete(int no) throws Exception;
// 글 작성
public void boardWrite(BoardDTO dto) throws Exception;
// 글 수정
public void boardEdit(BoardDTO dto) throws Exception;
// 페이징 처리
public List<Map<String, Object>> listAll(Criteria cri) throws Exception;
// 글 갯수
public int boardListCnt(BoardDTO dto) throws Exception;
}
package com.board.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.board.db.BoardDAO;
import com.board.db.BoardDTO;
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardDAO dao;
@Override
public List<BoardDTO> boardList() throws Exception {
return dao.boardList();
}
@Override
public BoardDTO boardDetail(int no) throws Exception {
return dao.boardDetail(no);
}
@Override
public void boardHit(int no) throws Exception {
dao.boardHit(no);
}
@Override
public void boardDelete(int no) throws Exception {
dao.boardDelete(no);
}
@Override
public void boardWrite(BoardDTO dto) throws Exception {
String title = dto.getTitle();
String content = dto.getContent();
String id = dto.getId();
dto.setTitle(title);
dto.setContent(content);
dto.setId(id);
dao.boardWrite(dto);
}
@Override
public void boardEdit(BoardDTO dto) throws Exception {
dao.boardEdit(dto);
}
@Override
public List<Map<String, Object>> listAll(Criteria cri) throws Exception {
return dao.listAll(cri);
}
@Override
public int boardListCnt(BoardDTO dto) throws Exception {
return dao.boardListCnt(dto);
}
}
BoardDAO.java / BoardDAOImpl.java
package com.board.db;
import java.util.List;
import java.util.Map;
import com.board.service.Criteria;
// DB 연동
public interface BoardDAO {
public List<BoardDTO> boardList() throws Exception;
public BoardDTO boardDetail(int no) throws Exception;
public void boardHit(int no) throws Exception;
public void boardDelete(int no) throws Exception;
public void boardWrite(BoardDTO dto) throws Exception;
public void boardEdit(BoardDTO dto) throws Exception;
public List<Map<String, Object>> listAll(Criteria cri) throws Exception;
public int boardListCnt(BoardDTO dto) throws Exception;
}
package com.board.db;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.board.service.Criteria;
@Repository
public class BoardDAOImpl implements BoardDAO {
@Autowired
private SqlSession sqlSession;
private static final String nameSpace = "com.board.mappers.boardMapper";
@Override
public List<BoardDTO> boardList() throws Exception {
return sqlSession.selectList(nameSpace + ".boardList");
}
@Override
public BoardDTO boardDetail(int no) throws Exception {
return sqlSession.selectOne(nameSpace + ".boardRead", no);
}
@Override
public void boardHit(int no) throws Exception {
sqlSession.update(nameSpace + ".boardHit", no);
}
@Override
public void boardDelete(int no) throws Exception {
sqlSession.update(nameSpace + ".boardDelete", no);
}
@Override
public void boardWrite(BoardDTO dto) throws Exception {
sqlSession.insert(nameSpace + ".boardWrite", dto);
}
@Override
public void boardEdit(BoardDTO dto) throws Exception {
sqlSession.update(nameSpace + ".boardEdit", dto);
}
@Override
public List<Map<String, Object>> listAll(Criteria cri) throws Exception {
return sqlSession.selectList("listAll", cri);
}
@Override
public int boardListCnt(BoardDTO dto) throws Exception {
return sqlSession.selectOne(nameSpace + ".baordListCnt", dto);
}
}
BoardDTO (model)
package com.board.db;
// 데이터 model
public class BoardDTO {
private int no;
private String title;
private String content;
private String date;
private String id;
private int hit;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getHit() {
return hit;
}
public void setHit(int hit) {
this.hit = hit;
}
}
BoardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.board.mappers.boardMapper">
<select id="boardList" resultType="BoardDTO">
SELECT * from board
</select>
<select id="boardRead" resultType="BoardDTO">
SELECT * from board WHERE
no=#{no}
</select>
<update id="boardHit">
UPDATE board SET hit = hit+1 WHERE no=#{no}
</update>
<delete id="boardDelete">
DELETE from board WHERE no=#{no}
</delete>
<insert id="boardWrite">
INSERT INTO board (title, content, date, id, hit)
values (#{title}, #{content}, now(), #{id}, 0)
</insert>
<update id="boardEdit">
UPDATE board SET title=#{title}, content=#{content},
date=now() WHERE no=#{no}
</update>
<select id="listAll" resultType="hashMap">
SELECT * from board ORDER BY no DESC LIMIT #{pageStart}, #{perPageNum}
</select>
<select id="baordListCnt" resultType="int">
SELECT COUNT(*) as boardCnt from board
</select>
</mapper>
페이징 처리
Criteria
package com.board.service;
public class Criteria {
private int page;
private int perPageNum;
public Criteria() {
this.page = 1;
this.perPageNum = 10;
}
public int getPageStart() {
return (this.page - 1) * perPageNum;
}
public int getPage() {
return page;
}
public void setPage(int page) {
if (page <= 0)
this.page = 1;
else {
this.page = page;
}
}
public int getPerPageNum() {
return perPageNum;
}
public void setPerPageNum(int pageCount) {
int cnt = this.perPageNum;
if (pageCount != cnt) {
this.perPageNum = cnt;
} else {
this.perPageNum = pageCount;
}
}
}
Paging
package com.board.service;
public class Paging {
private Criteria cri;
private int totalCount;
private int startPage;
private int endPage;
private boolean prev;
private boolean next;
private int displayPageNum = 10;
public Criteria getCri() {
return cri;
}
public void setCri(Criteria cri) {
this.cri = cri;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
calcData();
}
private void calcData() {
endPage = (int) (Math.ceil(cri.getPage() / (double) displayPageNum) * displayPageNum);
int tempEndPage = (int) (Math.ceil(totalCount / (double) cri.getPerPageNum()));
if (endPage > tempEndPage) {
endPage = tempEndPage;
}
startPage = (endPage - displayPageNum) + 1;
if (startPage <= 0)
startPage = 1;
prev = startPage == 1 ? false : true;
next = endPage * cri.getPerPageNum() >= totalCount ? false : true;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public boolean isPrev() {
return prev;
}
public void setPrev(boolean prev) {
this.prev = prev;
}
public boolean isNext() {
return next;
}
public void setNext(boolean next) {
this.next = next;
}
public int getDisplayPageNum() {
return displayPageNum;
}
public void setDisplayPageNum(int displayPageNum) {
this.displayPageNum = displayPageNum;
}
}
Views
- 무조건 views 경로 안에 있어야함
servlet-context.xml
<resources mapping="/resources/**" location="/resources/" />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.*" />
BoardList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Board List</title>
</head>
<body>
<jsp:include page="/WEB-INF/views/template/header.jsp" />
<div>
<h1>Board List</h1>
<c:if test="${sessionScope.id != null}">
<div style="float: right;">
<button type="button" onclick="location.href='./writePage'">글쓰기</button>
<button type="button" onclick="location.href='/'">Main</button>
</div>
</c:if>
<c:if test="${sessionScope.id eq null }">
<div style="float: right;">
<button type="button" onclick="location.href='/'">Main</button>
</div>
</c:if>
<div>
<div>
<table>
<thead>
<tr align="center">
<th scope="col">번호</th>
<th scope="col">작성자</th>
<th scope="col">제목</th>
<th scope="col">날짜</th>
<th scope="col">조회수</th>
</tr>
</thead>
<tbody>
<c:forEach items="${boardList}" var="boardList">
<tr align="center">
<td scope="row">${boardList.no}</td>
<td scope="row">${boardList.id}</td>
<td scope="row"><a href="/board/detail?no=${boardList.no}">${boardList.title}</a></td>
<td scope="row">${boardList.date}</td>
<td scope="row">${boardList.hit}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<ul style="margin: auto;">
<c:if test="${paging.prev }">
<li>
<a href='<c:url value="/board/list?page=${paging.startPage-1 }"/>'>
<i class="fa fa-chevron-left"></i>
</a></li>
</c:if>
<c:forEach begin="${paging.startPage }" end="${paging.endPage }" var="idx">
<c:choose>
<c:when test="${paging.cri.page eq idx}">
<li><b>
<a href='<c:url value="/board/list?page=${idx }"/>'>
<i class="fa">${idx } </i></a></b></li>
</c:when>
<c:otherwise>
<li>
<a href='<c:url value="/board/list?page=${idx }"/>'>
<i class="fa">${idx } </i></a></li>
</c:otherwise>
</c:choose>
</c:forEach>
<c:if test="${paging.next && paging.endPage >0 }">
<li>
<a href='<c:url value="/board/list?page=${paging.endPage+1 }"/>'>
<i class="fa fa-chevron-right"></i>
</a></li>
</c:if>
</ul>
</div>
</div>
</body>
</html>
BoardWrite.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Board Write</title>
</head>
<body>
<jsp:include page="/WEB-INF/views/template/header.jsp" />
<br>
<div style="float: none; margin: 0 auto;">
<h1 class="display-4" align="center">Board Write</h1>
<form method="post" action="/board/write">
<div>
<h6>작성자</h6>
<input type="text" value="${sessionScope.id}" name="id" readonly>
<h6>제목</h6>
<input type="text" placeholder="title" required name="title">
<h6>내용</h6>
<textarea type="textarea" placeholder="내용" required name="content"></textarea>
</div>
<div align="center">
<button type="submit">확인</button>
<button type="button" onclick="location.href='/board/list'">뒤로</button>
</div>
</form>
</div>
</body>
</html>
BoardDetail.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 charset="UTF-8">
<title>Board Read</title>
</head>
<body>
<jsp:include page="/WEB-INF/views/template/header.jsp" />
<div style="float: none; margin: 0 auto;">
<h1 class="display-4" align="center">Board Detail</h1>
<div>
<h6>글번호</h6>
<input name="id" type="text" value="${boardDetail.no}" readonly>
<h6>조회수</h6>
<input type="text" value="${boardDetail.hit}" readonly name="hit">
<h6>작성자</h6>
<input type="text" value="${boardDetail.id}" name="id" readonly>
<h6>제목</h6>
<input type="text" value="${boardDetail.title}" name="title" readonly>
<h6>내용</h6>
<textarea type="textarea" name="content" readonly>${boardDetail.content}</textarea>
<h6>날짜</h6>
<input type="text" name="date" value="${boardDetail.date}" readonly>
<c:if test="${sessionScope.id eq boardDetail.id }">
<button type="button" onclick="location.href='/board/editPage?no=${boardDetail.no}'">수정</button>
<button type="button" onclick="location.href='/board/delete?no=${boardDetail.no}'">삭제</button>
</c:if>
<button type="button" onclick="location.href='/board/list'">뒤로</button>
</div>
</div>
</body>
</html>
BoardEdit.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Board Edit</title>
<head>
<title>MVC 게시판</title>
</head>
<body>
<jsp:include page="/WEB-INF/views/template/header.jsp" />
<div style="float: none; margin: 0 auto;">
<h1 class="display-4" align="center">Board Edit</h1>
<form action="/board/edit" method="post">
<input type="hidden" name="no" value="${boardEdit.no}"></input>
<div>
<h6>작성자</h6>
<input type="text" value="${boardEdit.id}" name="id" readonly>
<h6>제목</h6>
<input type="text" value="${boardEdit.title}" name="title">
<h6>내용</h6>
<textarea type="textarea" name="content">${boardEdit.content}</textarea>
<h6>날짜</h6>
<input type="text" value="${boardEdit.date}" name="date" readonly>
</div>
<div align="center">
<button type="submit">수정</button>
<button type="button" onclick="location.href='/board/detail?no=${boardEdit.no}'">뒤로</button>
</div>
</form>
</div>
</body>
</html>