Stack/Spring

[Spring] CRUD Project 제작 3 - 조회수 / 페이지 번호 게시판 (완성)

7ingout 2022. 9. 14. 15:38

1. 게시글 조회수 기능 구현

1) Mapper에 쿼리 작성

board-Mapper.xml

<update id="updateViewCnt">
    update tbl_board
    set viewcnt = viewcnt +1
    where bno =
    #{bno}
</update>

 

2) 인터페이스 메소드 추가

void updateViewCnt(Integer bno) throws Exception;

 

3) DAO 구현

@Override	    
public void updateViewCnt(Integer bno) throws Exception {	      
	session.update(namespace + ".updateViewCnt", bno);	   
}

 

4) service 구현에 read 메소드 내부에 끼워넣기

dao.updateViewCnt(bno);

	@Override
	public BoardVO read(Integer bno) throws Exception {
		dao.updateViewCnt(bno);
		return dao.read(bno);
	}

 

2. 게시글 페이지번호 구현

1)

- TypeAliase 설정

- src\main\resources 폴더의 mybatis-config.xml에 typeAliases 추가

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD COnfig 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<typeAliases>
	    <package name="com.myp.domain"/>
	</typeAliases>
</configuration>

 

2) 쿼리작성

mapper

<select id="listPage" resultType="BoardVO">
        <![CDATA[ select
            bno, title, content, writer, regdate, viewcnt
            from
            tbl_board
            where bno > 0
            order by bno desc, regdate desc
            limit #{page}, 10
        ]]>
	</select>

	<select id="listCriteria" resultType="BoardVO">
	<![CDATA[
	select
	bno, title, content, writer, regdate, viewcnt
	from
	tbl_board
	where bno > 0
	order by bno desc, regdate desc
	limit #{pageStart}, #{perPageNum}
	]]>
	</select>

	<select id="countPaging" resultType="int">
	<![CDATA[select
	count(bno) 
	from
	tbl_board
	where
	bno > 0
	]]>
	</select>

 

3) 추가된 쿼리 대응 클래스 추가

com.myp.domain

Criteria.java

package com.myp.domain;

public class Criteria { // 페이징 기준을 정의하는 클래스
	private int page;
	private int perPageNum;

	public Criteria() {  this.page = 1;  this.perPageNum = 10; }

	public void setPage(int page) {  if (page <= 0) {   this.page = 1;   return;  }  this.page = page; }

	public void setPerPageNum(int perPageNum) {  if (perPageNum <= 0 || perPageNum > 100) {   this.perPageNum = 10;   return;  }  this.perPageNum = perPageNum; }

	public int getPage() {  return page; } 
	// method for MyBatis SQL Mapper - 
	public int getPageStart() { 
		return (this.page - 1) * perPageNum;
	}
	// method for MyBatis SQL Mapper
	public int getPerPageNum() {
		return this.perPageNum;}
	@Override public String toString() {
		return "Criteria [page=" + page + ", "
	+ "perPageNum=" + perPageNum + "]";
		}
	}

 

4) 페이징 계산용 클래스 추가

com.myp.domain

PageMaker.java

package com.myp.domain;

import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

public class PageMaker { // 페이징 계산용 클래스
	private int totalCount;
	private int startPage;
	private int endPage;
	private boolean prev;
	private boolean next;
	private int displayPageNum = 10;
	private Criteria cri;

	public void setCri(Criteria cri) {  this.cri = cri; }

	public void setTotalCount(int totalCount) {  this.totalCount = totalCount;  calcData(); }

	private void calcData() {  endPage = (int) (Math.ceil(cri.getPage() / (double) displayPageNum) * displayPageNum);  
	startPage = (endPage - displayPageNum) + 1;  
	int tempEndPage = (int) (Math.ceil(totalCount / (double) cri.getPerPageNum()));  
	if (endPage > tempEndPage) {   endPage = tempEndPage;  } 
	prev = startPage == 1 ? false : true;  
	next = endPage * cri.getPerPageNum() >= totalCount ? false : true; }

	public int getTotalCount() {  return totalCount; }

	public int getStartPage() {  return startPage; }

	public int getEndPage() {  return endPage; }

	public boolean isPrev() {  return prev; }

	public boolean isNext() {  return next; }

	public int getDisplayPageNum() {  return displayPageNum; }

	public Criteria getCri() {  return cri; }

	public String makeQuery(int page) {  
		UriComponents uriComponents = 
		UriComponentsBuilder.newInstance().queryParam("page", page)    
			.queryParam("perPageNum", cri.getPerPageNum()).build();  
		return uriComponents.toUriString(); 
	}
}

 

5) DAO 인터페이스 추가

BoardDAO.java

	public List<BoardVO> listAll() throws Exception;
	public List<BoardVO> listPage(int page) throws Exception;
	public List<BoardVO> listCriteria(Criteria cri) throws Exception;

 

6) 오버라이드

BoardDAOImpl.java

@Override
	public List<BoardVO> listPage(int page) throws Exception {
		if (page <= 0) {
			page = 1;
		}
		page = (page - 1) * 10;
		return session.selectList(namespace + ".listPage", page);
	}

	@Override
	public List<BoardVO> listCriteria(Criteria cri) throws Exception {
		return session.selectList(namespace + ".listCriteria", cri);
	}

	@Override
	public int countPaging(Criteria cri) throws Exception {
		return session.selectOne(namespace + ".countPaging", cri);
	}

 

7) Service 인터페이스 추가

BoardSservice.java

public List<BoardVO> listCriteria(Criteria cri) throws Exception; // 페이징 계산용	  
public int listCountCriteria(Criteria cri) throws Exception; // DB의 데이터 카운팅을 위한 메소드

 

8) 오버라이드

BoardServiceImpl.java

	@Override
	public List<BoardVO> listCriteria(Criteria cri) throws Exception {
		return dao.listCriteria(cri);
	}

	@Override
	public int listCountCriteria(Criteria cri) throws Exception {
		return dao.countPaging(cri);
	}

 

9) listPage.jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%><%@ taglib
	uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><%@ taglib
	prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%><%@ page
	session="false"%><!DOCTYPE html>
<html>
<head>
<title>게시판 목록</title>
</head>
<form action="regist" method="get">
	<body>
		<table border="1" width="880">
			<tr>
				<td width="77">
					<p align="center">글번호</p>
				</td>
				<td width="327">
					<p align="center">제목</p>
				</td>
				<td width="197">
					<p align="center">작성자</p>
				</td>
				<td width="155">
					<p align="center">작성일</p>
				</td>
				<td width="90">
					<p align="center">조회수</p>
				</td>
			</tr>
			<c:forEach items="${list}" var="boardVO">
				<tr>
					<td>${boardVO.bno}</td>
					<td><a href='/read?bno=${boardVO.bno}'>${boardVO.title}</a></td>
					<td>${boardVO.writer}</td>
					<td><fmt:formatDate pattern="yyyy-MM-dd HH:mm"
							value="${boardVO.regdate}" /></td>
					<td><span class="badge bg-red">${boardVO.viewcnt}</span></td>
				</tr>
			</c:forEach>
		</table>
		<c:if test="${pageMaker.prev}">
			<a href="listPage${pageMaker.makeQuery(pageMaker.startPage - 1) }">«</a>
		</c:if>
		<c:forEach begin="${pageMaker.startPage }" end="${pageMaker.endPage }"
			var="idx">
			<c:out value="${pageMaker.cri.page == idx?'':''}" />
			<a href="listPage${pageMaker.makeQuery(idx)}">${idx}</a>
		</c:forEach>
		<c:if test="${pageMaker.next && pageMaker.endPage > 0}">
			<a href="listPage${pageMaker.makeQuery(pageMaker.endPage +1) }">
				» </a>
		</c:if>
		<br>
		<button type="submit">글쓰기</button>
	</body>
</form>
</html>

 

10) controller 메소드 추가

	@RequestMapping(value = "/listPage", method = RequestMethod.GET)
	public void listPage(@ModelAttribute("cri") Criteria cri, Model model) throws
	Exception {
		model.addAttribute("list", service.listCriteria(cri)); // JSP에 계산된 페이징 출력
		PageMaker pageMaker = new PageMaker(); // 객체생성	
		pageMaker.setCri(cri); // setCri 메소드 사용
		pageMaker.setTotalCount(service.listCountCriteria(cri)); // 전체 게시글 갯수 카운트
		model.addAttribute("pageMaker", pageMaker);
	}

 

11) remove, modify, regist 메소드 수정

package com.myp.controller;

import javax.inject.Inject;

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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.myp.domain.BoardVO;
import com.myp.domain.Criteria;
import com.myp.domain.PageMaker;
import com.myp.service.BoardService;

@Controller // 컨트롤러임을 명시
@RequestMapping(value = "/") // 주소 패턴
public class BoardController {

	@Inject // 주입(심부름꾼) 명시
	private BoardService service; // Service 호출을 위한 객체생성

	@RequestMapping(value = "/listAll", method = RequestMethod.GET) // 주소 호출 명시 . 호출하려는 주소 와 REST 방식설정 (GET)
	public void listAll(Model model) throws Exception { // 메소드 인자값은 model 인터페이스(jsp전달 심부름꾼)
		model.addAttribute("list", service.listAll()); // jsp에 심부름할 내역(서비스 호출)
	}

	@RequestMapping(value = "/regist", method = RequestMethod.GET) // GET 방식으로 페이지 호출
	public void registerGET(BoardVO board, Model model) throws Exception {

	}

	@RequestMapping(value = "/regist", method = RequestMethod.POST) // POST방식으로 내용 전송
	public String registPOST(BoardVO board, RedirectAttributes rttr) throws Exception { // 인자값으로 REDIRECT 사용 
		service.regist(board); // 글작성 서비스 호출

		return "redirect:/listPage"; // 작성이 완료된 후, 목록페이지로 리턴
	}

	@RequestMapping(value = "/read", method = RequestMethod.GET) // GET 방식으로 페이지 호출
	public void read(@RequestParam("bno") int bno, Model model) throws Exception {
		// 인자값은 파라미터 값으로 기본키인 글번호를 기준으로 Model을 사용하여 불러옴
		model.addAttribute(service.read(bno)); // read 서비스 호출
	}

	@RequestMapping(value = "/modify", method = RequestMethod.GET) // GET 방식으로 페이지 호출
	public void modifyGET(int bno, Model model) throws Exception {
		model.addAttribute(service.read(bno)); // 수정을 위한 글읽기 서비스 호출
	}

	@RequestMapping(value = "/modify", method = RequestMethod.POST) // POST방식으로 데이터 전송
	public String modifyPOST(BoardVO board, RedirectAttributes rttr) throws Exception {
		service.modify(board); // 글수정 서비스 호출
		return "redirect:/listPage"; // 수정이 완료된 후, 목록페이지로 리턴
	}

	@RequestMapping(value = "/remove", method = RequestMethod.POST) // POST방식으로 데이터 전송
	public String removePOST(@RequestParam("bno") int bno, RedirectAttributes rttr) throws Exception {
		service.remove(bno); // 글삭제 서비스 호출
		return "redirect:/listPage"; // 삭제가 완료된 후, 목록페이지로 리턴
	}

	@RequestMapping(value = "/listPage", method = RequestMethod.GET)
	public void listPage(@ModelAttribute("cri") Criteria cri, Model model) throws
	Exception {
		model.addAttribute("list", service.listCriteria(cri)); // JSP에 계산된 페이징 출력
		PageMaker pageMaker = new PageMaker(); // 객체생성	
		pageMaker.setCri(cri); // setCri 메소드 사용
		pageMaker.setTotalCount(service.listCountCriteria(cri)); // 전체 게시글 갯수 카운트
		model.addAttribute("pageMaker", pageMaker);
	}
	
	@RequestMapping(path = "/index", method = RequestMethod.GET)
	public void index() {

	}
}

 

12) home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ page session="false"%>
<html>
<head>
<title>Home</title>
<link href="/resources/css/test.css" rel="stylesheet"/>
</head>
<body>
<form action="listAll" method="get">
	<div>
		<button type="submit">CRUD게시판 가기</button>
		<h1>Hello world!  </h1>
		<P>  The time on the server is ${serverTime}.</P>
	</div>
</form>
<form action="listPage" method="get">
	<div>
		<button type="submit">CRUD 번호게시판 가기</button>
	</div>
</form>
<a href="index"><button>인덱스</button></a>
</form>
</body>
</html>

 

 

출처: https://chan-0124.tistory.com/entry/[스프링]게시글-페이지번호-구현1-(비지니스-파트)?category=639554 [L.C.H`s BLOG:티스토리]