고래씌
[Spring] 6-1. 게시판 목록, 페이징 본문
1. 게시판 목록
▶ boardListView.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>Insert title here</title>
<style>
#boardList {text-align:center;}
#boardList>tbody>tr:hover {cursor:pointer;}
#pagingArea {width:fit-content; margin:auto;}
#searchForm {
width:80%;
margin:auto;
}
#searchForm>* {
float:left;
margin:5px;
}
.select {width:20%;}
.text {width:53%;}
.searchBtn {width:20%;}
/* 썸네일 관련 스타일 */
#boardList tr > td:nth-of-type(2){ /* 2번째 td(제목) */
position: relative;
}
.list-thumbnail{
max-width: 50px;
max-height: 30px;
position: absolute;
left : -15px;
top : 10px;
}
</style>
</head>
<body>
<jsp:include page="/WEB-INF/views/common/header.jsp" />
<div class="content">
<br><br>
<div class="innerOuter" style="padding:5% 10%;">
<h2>일반게시판</h2>
<br><br>
<c:if test="${not empty loginUser}"> <!-- 로그인 유저가 비어있지 않으면 -->
<a class="btn btn-secondary" style="float:right" href="">
글쓰기
</a>
</c:if>
<br>
<table id="boardList" class="table table-hover" align="center">
<thead>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>작성일</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="5">게시글이 없습니다.</td>
</tr>
</tbody>
</table>
<br>
<!-- 페이징 -->
<div id="pagingArea">
<ul class="pagination">
<li class="page-item">
<a class="page-link">Previous</a>
</li>
<li class="page-item">
<a class="page-link">1</a>
</li>
<li class="page-item">
<a class="page-link">2</a>
</li>
<li class="page-item">
<a class="page-link">3</a>
</li>
<li class="page-item">
<a class="page-link">4</a>
</li>
<li class="page-item">
<a class="page-link">5</a>
</li>
<li class="page-item">
<a class="page-link">6</a>
</li>
<li class="page-item">
<a class="page-link">7</a>
</li>
<li class="page-item">
<a class="page-link">8</a>
</li>
<li class="page-item">
<a class="page-link">9</a>
</li>
<li class="page-item">
<a class="page-link">10</a>
</li>
<li class="page-item">
<a class="page-link">Next</a>
</li>
</ul>
</div>
<!-- 검색기능 -->
<br clear="both"> <!-- float 속성 해제 -->
<form id="searchForm" method="get" align="center">
<div class="select">
<select class="custom-select" name="condition">
<option value="writer">작성자</option>
<option value="title">제목</option>
<option value="content">내용</option>
<option value="titleAndContent">제목+내용</option>
</select>
</div>
<div class="text">
<input type="text" class="form-control" name="keyword" />
</div>
<button type="submit" class="searchBtn btn btn-secondary">검색</button>
</form>
</div>
</div>
<jsp:include page="/WEB-INF/views/common/footer.jsp" />
</body>
</html>
=> 다음과 같이 폴더 및 파일 생성(BoardDao, BoardService는 interface 파일임)
▶ Board.java
package com.kh.spring.board.model.vo;
import java.sql.Date;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor // 기본생성자
@AllArgsConstructor
@Data // setter, getter, ...
public class Board {
private int boardNo;
private String boardTitle;
private String boardContenxt;
private String boardWrither; // id, userNo, name 동시에 저장
private int count;
private Date createDate;
private String status;
private String orginName;
private String changeName;
private String boardCd; // boardType의 일반게시판, 사진게시판 등
}
▶ BoardType.java => 게시판 종류를 저장하는 vo객체
package com.kh.spring.board.model.vo;
import lombok.Data;
@Data
public class BoardType {
private String boardCd;
private String boardName; // 일반게시판, 사진게시판, 음악, 영화, 게임
}
- BoardController.java
=> BoardController.java 맨위에 로그를 기록하기 위해 Slf4j를 등록하고 다음과 같이 등록
- BoardServiceImpl.java에는 다음과 같이 추가
- BaordDaoImpl.java에는 다음과 같이 추가
▶ BoardController.java
=> 이 방법으로하게 되면 게시판 타입이 100개라면 그 100개를 일일이 다 추가해야하는 번거러움이 발생한다!
=> 그래서 동적파라미터를 설정하여 이용하여 설정하도록 하겠다!
=> 동적파라미터 설정 : {변수명} / 리액트에서는 : 변수명 으로 적었었음
@GetMapping("/list/{boardCode}") // 그럼 뒤에 C가되었든, T가되었든 다 받아준다!
public String selectList(@PathVariable("boardCode") String boardCode,
@RequestParam(value="currentPage", defaultValue="1") int currentPage, // currentPage는 매개변수로 얻어옴
Model model, // Request Scope를 저장하기 위해서 model 사용
@RequestParam Map<String, Object> paramMap) {
// @PathVariable(변수명) : URL경로로 포함되어있는 값을 변수로 사용 가능
// + PathVariable로 등록한 변수는 자동으로 requestScope에 저장이 된다.
paramMap.put("boardCode", boardCode);
log.info("paramMap = {}", paramMap); // 내가 두번째 매개변수로 넣은 데이터가 저기 {}로 안으로 추가가 됨
// slf4j에서 제공하고있는 로그를 이용. 앞으로는 출력문 대신에 log.info를 이용!
// 1) 게시글 갯수 카운팅
// 2) PageInfo 생성
// 3) 게시글목록 조회후
// 4) pageInfo, list를 model에 추가
return "board/boardListView";
}
☞ @PathVariable(변수명) : URL경로로 포함되어있는 값을 변수로 사용 가능
+ PathVariable로 등록한 변수는 자동으로 requestScope에 저장이 된다.
☞ log.info 앞으로는 출력문 대신에 log.info를 이용한다! => 로그가 출력됨
=> 여기 1), 2), 3), 4)를 모두 처리하기위해(BoardController) 추가할 예정
=> 아래에 페이징과 함께 처리하여 추가하도록 하겠다.
2. 페이징 처리, 게시글 목록
▶ PageInfo.java
package com.kh.spring.common.model.vo;
import lombok.Data;
@Data
public class PageInfo {
private int listCount;
private int currentPage;
private int pageLimit;
private int boardLimit;
private int maxPage;
private int startPage; // 시작페이지
private int endPage; // 종료페이지
}
▶ Pagination.java
package com.kh.spring.common.template;
import com.kh.spring.common.model.vo.PageInfo;
public class Pagination {
public static PageInfo getPaageInfo(int listCount, int currentPage, int pageLimit, int boardLimit) {
int maxPage =(int)(Math.ceil(((double)listCount/boardLimit)));
int startPage = (currentPage-1) / pageLimit * pageLimit+1;
int endPage = startPage+pageLimit-1;
if(endPage>maxPage) {
endPage=maxPage;
}
PageInfo pageinfo = new PageInfo();
pageinfo.setBoardLimit(boardLimit);
pageinfo.setCurrentPage(currentPage);
pageinfo.setEndPage(endPage);
pageinfo.setListCount(listCount);
pageinfo.setMaxPage(maxPage);
pageinfo.setPageLimit(pageLimit);
pageinfo.setStartPage(startPage);
return pageinfo;
}
}
▶ boardListView.java
<%@ 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>Insert title here</title>
<style>
#boardList {text-align:center;}
#boardList>tbody>tr:hover {cursor:pointer;}
#pagingArea {width:fit-content; margin:auto;}
#searchForm {
width:80%;
margin:auto;
}
#searchForm>* {
float:left;
margin:5px;
}
.select {width:20%;}
.text {width:53%;}
.searchBtn {width:20%;}
/* 썸네일 관련 스타일 */
#boardList tr > td:nth-of-type(2){ /* 2번째 td(제목) */
position: relative;
}
.list-thumbnail{
max-width: 50px;
max-height: 30px;
position: absolute;
left : -15px;
top : 10px;
}
</style>
</head>
<body>
<jsp:include page="/WEB-INF/views/common/header.jsp" />
<div class="content">
<br><br>
<div class="innerOuter" style="padding:5% 10%;">
<h2>일반게시판</h2>
<br><br>
<c:if test="${not empty loginUser}"> <!-- 로그인 유저가 비어있지 않으면 -->
<a class="btn btn-secondary" style="float:right" href="">
글쓰기
</a>
</c:if>
<br>
<table id="boardList" class="table table-hover" align="center">
<thead>
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>작성일</th>
</tr>
</thead>
<tbody>
<c:choose>
<c:when test="${empty list }"> <!-- 게시글이 없다면 -->
<tr>
<td colspan="5">게시글이 없습니다.</td>
</tr>
</c:when>
<c:otherwise>
<c:forEach var="board" items="${list }">
<tr>
<td>${board.boardNo }</td>
<td>${board.boardTitle }</td>
<td>${board.boardWriter }</td>
<td>${board.count}</td>
<td>${board.createDate }</td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</tbody>
</table>
<br>
<!-- 페이징 -->
<c:set var="url" value="${boardCode}?currentPage="/>
<div id="pagingArea">
<ul class="pagination">
<%-- <c:if test="${pi.currentPage eq 1}" > <!-- currentPage가 1과 같을때 --> --%>
<!-- <li class="page-item"> -->
<!-- 절대경로 방식 -->
<%-- <a href="${contextPath}/board/list/${boardCode}?currentPage=${pi.currentPage -1}" class="page-link">Previous</a> --%>
<!-- 상대경로 방식 -->
<!-- <a class="page-link">Previous</a> -->
<!-- </li> -->
<%-- </c:if> --%>
<c:if test="${pi.currentPage ne 1}">
<li class="page-item">
<!-- 절대경로 방식 -->
<%-- <a href="${contextPath}/board/list/${boardCode}?currentPage=${pi.currentPage -1}" class="page-link">Previous</a> --%>
<!-- 상대경로 방식 -->
<a href="${url}${pi.currentPage -1}" class="page-link">Previous</a>
</li>
</c:if>
<c:forEach var="p" begin="${pi.startPage }" end="${pi.endPage }">
<li class="page-item">
<a href="${url}${p}" class="page-link">${p}</a>
</li>
</c:forEach>
<%-- <c:if test="${pi.currentPage eq pi.maxPage }"> --%>
<!-- <li class="page-item"> -->
<!-- <a class="page-link">NEXT</a> -->
<!-- </li> -->
<%-- </c:if> --%>
<c:if test="${pi.currentPage ne pi.maxPage }" >
<li class="page-item">
<a href="${url}${pi.currentPage +1}" class="page-link">NEXT</a>
<%-- <a href="${boardCode}?currentPage=${pi.currentPage +1}" class="page-link">NEXT</a> --%>
</li>
</c:if>
</ul>
</div>
<!-- 검색기능 -->
<br clear="both"> <!-- float 속성 해제 -->
<form id="searchForm" method="get" align="center" action="${boardCode}" >
<div class="select">
<select class="custom-select" name="condition">
<option value="writer">작성자</option>
<option value="title">제목</option>
<option value="content">내용</option>
<option value="titleAndContent">제목+내용</option>
</select>
</div>
<div class="text">
<input type="text" class="form-control" name="keyword" />
</div>
<button type="submit" class="searchBtn btn btn-secondary">검색</button>
</form>
</div>
</div>
<jsp:include page="/WEB-INF/views/common/footer.jsp" />
</body>
</html>
▶ BoardController.java
int listCount = boardService.selectListCount(paramMap); | List<Board> list = boardService.selectList(pi, paramMap); |
=> paramMap을 넣는 이유는 map형태의 데이터여서 좀 더 다양한 형태의 값을 추가할 수 있음!
@GetMapping("/list/{boardCode}") // 그럼 뒤에 C가되었든, T가되었든 다 받아준다!
public String selectList(@PathVariable("boardCode") String boardCode,
@RequestParam(value="currentPage", defaultValue="1") int currentPage, // currentPage는 매개변수로 얻어옴
Model model, // Request Scope를 저장하기 위해서 model 사용
@RequestParam Map<String, Object> paramMap) {
// @PathVariable(변수명) : URL경로로 포함되어있는 값을 변수로 사용 가능
// + PathVariable로 등록한 변수는 자동으로 requestScope에 저장이 된다.
paramMap.put("boardCode", boardCode);
log.info("paramMap = {}", paramMap); // 내가 두번째 매개변수로 넣은 데이터가 저기 {}로 안으로 추가가 됨
// slf4j에서 제공하고있는 로그를 이용. 앞으로는 출력문 대신에 log.info를 이용!
// 1) 게시글 갯수 카운팅
int listCount = boardService.selectListCount(paramMap); // map형태의 데이터여서 좀더 다양한 형태의 값을 추가할 수 있음
int pageLimit = 10;
int boardLimit = 5;
// 2) PageInfo 생성
PageInfo pi = Pagination.getPaageInfo(listCount, currentPage, pageLimit, boardLimit);
// 3) 게시글목록 조회후
List<Board> list = boardService.selectList(pi, paramMap);
// 4) pageInfo, list를 model에 추가
model.addAttribute("list", list);
model.addAttribute("pi", pi);
model.addAttribute("param",paramMap); // boardCode값 전달
log.info("BoardList=", list);
System.out.println(list);
return "board/boardListView";
}
▶ BoardService.java
package com.kh.spring.board.model.service;
import java.util.List;
import java.util.Map;
import com.kh.spring.board.model.vo.Board;
import com.kh.spring.common.model.vo.PageInfo;
public interface BoardService {
// 페이징 처리
int selectListCount(Map<String, Object> paramMap);
// 게시판 목록
List<Board> selectList(PageInfo pi, Map<String, Object> paramMap);
}
▶ BoardServiceImpl.java
package com.kh.spring.board.model.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.kh.spring.board.model.dao.BoardDao;
import com.kh.spring.board.model.vo.Board;
import com.kh.spring.common.model.vo.PageInfo;
import lombok.extern.slf4j.Slf4j;
@Slf4j // 로그
@Service
public class BoardServiceImpl implements BoardService{
@Autowired
private BoardDao boardDao;
// 페이징
@Override
public int selectListCount(Map<String, Object> paramMap) {
return boardDao.selectListCount(paramMap);
}
// 게시판 목록
@Override
public List<Board> selectList(PageInfo pi, Map<String, Object> paramMap) {
return boardDao.selectList(pi, paramMap);
}
}
▶ BoardDao.java
package com.kh.spring.board.model.dao;
import java.util.List;
import java.util.Map;
import com.kh.spring.board.model.vo.Board;
import com.kh.spring.common.model.vo.PageInfo;
public interface BoardDao {
// 페이징
int selectListCount(Map<String, Object> paramMap);
// 게시글 목록
List<Board> selectList(PageInfo pi, Map<String, Object> paramMap);
}
▶ BoardDaoImpl.java
package com.kh.spring.board.model.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.kh.spring.board.model.vo.Board;
import com.kh.spring.common.model.vo.PageInfo;
@Repository
public class BoardDaoImpl implements BoardDao{
@Autowired
private SqlSession sqlSession;
// 페이징
@Override
public int selectListCount(Map<String, Object> paramMap) {
return sqlSession.selectOne("boardMapper.selectListCount", paramMap);
}
// 게시글 목록
@Override
public List<Board> selectList(PageInfo pi, Map<String, Object> paramMap) {
int offset = (pi.getCurrentPage()-1) * pi.getBoardLimit();
int limit = pi.getBoardLimit();
RowBounds rowBounds = new RowBounds(offset, limit);
return sqlSession.selectList("boardMapper.selectList", paramMap, rowBounds); // 만약 넘길게 없다면 null이라도 선언해야함(두번째 매개변수)
}
}
▶ board-mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="boardMapper">
<!-- 페이징 -->
<select id="selectListCount" parameterType="map" resultType="int">
SELECT COUNT(*)
FROM BOARD
WHERE STATUS = 'Y' AND BOARD_CD= #{boardCode}
</select>
<!-- 게시글 목록 -->
<!-- 결과값은 board로 담아줘야함 -->
<select id="selectList" resultType="board" parameterType="map">
SELECT BOARD_NO, BOARD_TITLE, M.USER_NAME AS BOARD_WRITER, BOARD_CONTENT, COUNT, CREATE_DATE
FROM BOARD B
LEFT JOIN MEMBER M ON (BOARD_WRITER = USER_NO)
WHERE B.STATUS='Y' AND BOARD_CD= #{boardCode}
ORDER BY BOARD_NO DESC
</select>
</mapper>
'Server > Spring' 카테고리의 다른 글
[Spring] 7. Application 전역에 있는 데이터를 저장(Intercepter) (0) | 2024.01.24 |
---|---|
[Spring] 6-2. 게시판 검색기능 (0) | 2024.01.24 |
[Spring] 5. 비동기 요청 처리 기능(아이디 중복검사, 회원 정보 조회) (0) | 2024.01.23 |
[Spring] 4. 예외처리 (0) | 2024.01.23 |
[Spring] 3. 마이페이지 수정하기, alertMsg 띄우기 (0) | 2024.01.23 |