💫 페이징이 된 모습을 보기 위해 Borad를 복사해 PagingBorad 폴더를 만들었다.
<aside> 📌 [첫번째 페이지] [이전 블럭] [1] [2] [3] [4] [5] [다음 블럭] [마지막 페이지]
</aside>
최종적으로 구현하고 싶은 모양이다.
각 페이지 번호를 누르면 페이지 넘버를 파라매터로 받아야한다.
그리고 파라매터로 받은 페이지 넘버가 주소에 표시되어야 한다. → url 정보를 넘겨줘야 함.
List.jsp
<%@page import="utils.BoardPage"%>
<%@page import="model1.board.BoardDAO"%>
<%@page import="model1.board.BoardDTO"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
// DB에 연결
BoardDAO dao = new BoardDAO(application);
// form에서 액션 속성 생략 -> 자기 자신 페이지를 파라매터로 받는다.
String searchField = request.getParameter("searchField");
String searchWord = request.getParameter("searchWord");
Map<String, Object> param = new HashMap<>();
// 검색조건으로 검색하려 할때
if (searchWord != null) {
param.put("searchField", searchField);
param.put("searchWord", searchWord);
}
// 전체 개수 구하기 selectCount()
// 검색 했을 때 개수 dao.selectCount(param)
// boardLists 에 DTO의 정보가 들어있다.
int totalCount = dao.selectCount(param);
int pageSize = Integer.parseInt(application.getInitParameter("POSTS_PER_PAGE"));
int blockPage = Integer.parseInt(application.getInitParameter("PAGES_PER_BLOCK"));
int totalPage = (int) Math.ceil( (double)totalCount / pageSize );
// 페이지 번호를 관리하는 변수
int pageNum = 1;
// 페이지 번호를 다른 걸로 선택하면 그 다른 페이지 번호를 받아온다
String pageTemp = request.getParameter("pageNum");
if (pageTemp != null && !pageTemp.equals("")){
pageNum = Integer.parseInt(pageTemp);
}
// 게시물의 시작번호와 끝 번호 구하기
int start = (pageNum - 1) * pageSize + 1;
int end = pageNum * pageSize;
param.put("start", start);
param.put("end", end);
/* List<BoardDTO> boardLists = dao.selectList(param); */
List<BoardDTO> boardLists = dao.selectListPage(param);
dao.close();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<jsp:include page="../Common/Link.jsp" />
<h2>목록 보기(List)</h2>
<!-- 폼태그에 action 속성이 생략되면 자신의 현재 페이지를 요청한다. (List.jsp)-->
<form method="get">
<table border="1" width="90%">
<tr>
<td align="center">
<select name="searchField">
<option value="title">제목</option>
<option value="content">내용</option>
</select>
<input type="text" name="searchWord" />
<input type="submit" value="검색하기" />
</td>
</tr>
</table>
</form>
<table border="1" width="90%">
<tr>
<th width="10%">번호</th>
<th width="50%">제목</th>
<th width="15%">작성자</th>
<th width="10%">조회수</th>
<th width="15%">작성일</th>
</tr>
<!-- 게시물이 없을 떄 -->
<% if (boardLists.isEmpty()) {%>
<tr>
<td colspan="5" align="center">등록된 게시물이 없습니다^^*</td>
</tr>
<% }else{
int virtualNum = 0;
for(BoardDTO dto : boardLists){
virtualNum = totalCount--;
%>
<!-- 게시물이 있을 때 -->
<tr align="center">
<!-- DTO에서 쓴 이름과 같게 -->
<%-- <td><%= dto.getNum() %></td> --%>
<td><%= virtualNum %></td>
<td>
<a href="View.jsp?num=<%= dto.getNum() %>"> <%= dto.getTitle() %> </a>
</td>
<td><%= dto.getId() %></td>
<td><%= dto.getVisitcount() %></td>
<td><%= dto.getPostDate() %></td>
</tr>
<%
} // for문
} // if else문
%>
</table>
<table border="1" width="90%">
<tr align="center">
<td>
<!-- [첫번째 페이지] [이전 블럭] [1] [2] [3] [4] [5] [다음 블럭] [마지막 페이지] -->
<!-- request.getRequestURI()로 주소값을 가지고 올 수 있다 -->
<%= BoardPage.pagingStr(totalCount, pageSize, blockPage, pageNum, request.getRequestURI()) %>
</td>
<td align="right">
<button type="button" onclick="location.href='write.jsp'">글쓰기</button>
</td>
</tr>
</table>
</body>
</html>
BoardPage.jsp
package utils;
public class BoardPage {
public static String pagingStr(int totalCount, int pageSize, int blockPage, int pageNum, String reqUrl) {
String pagingStr = "";
// 전체 페이지수 계산 , totalPages = 마지막 페이지 수
int totalPages = (int) Math.ceil( (double)totalCount / pageSize );
// 이전 페이지 블록 바로가기 출력
// ( (현재 페이지 - 1 ) / PAGES_PER_BLOCK) ) * PAGES_PER_BLOCK + 1
int pageTemp = ((pageNum - 1 ) / blockPage) * blockPage + 1;
// 현재페이지의 시작 값이 1이면 [첫 페이지]와 [이전 블록]은 안보인다.
if(pageTemp != 1) {
pagingStr += "<a href='" + reqUrl + "?pageNum=1'>[첫 페이지]</a>";
pagingStr += " ";
pagingStr += "<a href='" + reqUrl + "?pageNum=" + (pageTemp - 1) + "'>[이전 블록]</a>";
}
// 각 블록에 페이지 번호 출력
int blockCount = 1;
while ( blockPage >= blockCount && pageTemp <= totalPages ) {
// 마지막 블록에도 번호 비활성화
// 현재 선택한 번호 비활성화
if (pageTemp == pageNum) {
pagingStr += " [" + pageTemp + "] ";
} else {
pagingStr += " <a href='" + reqUrl + "?pageNum=" + pageTemp + "'>[" + pageTemp + "]</a> ";
}
pageTemp++; // 6 7 8 9 10 다음 블록으로 넘아가 11
blockCount++; // 1 2 3 4 5 다음 블록 6
}
// System.out.println(pageTemp + " : " + totalCount);
// 다음 페이지 블록 바로가기 출력
if(pageTemp <= totalPages) {
pagingStr += "<a href='" + reqUrl + "?pageNum=" + (pageTemp) + "'>[다음 블록]</a>";
pagingStr += " ";
pagingStr += "<a href='" + reqUrl + "?pageNum=" + totalPages + "'>[마지막 페이지]</a>";
}
return pagingStr;
}
}
BoardDAO.java
package model1.board;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import common.JDBConnect;
import jakarta.servlet.ServletContext;
public class BoardDAO extends JDBConnect {
public BoardDAO(ServletContext application) {
super(application);
}
// 1. 검색 조건에 맞는 게시물의 개수를 반환합니다.
public int selectCount(Map<String, Object> map) {
int totalcount = 0;
// 복잡한 쿼리문은 오류날 확률이 높으므로 디벨로퍼에서 미리 실행해보고 옮기는 것이 좋다.
String query = " select count(*) from board ";
// searchWord를 선택하면 이름, 내용으로 분류해서 count 해줘야 한다.
if (map.get("searchWord") != null) {
query += " where " + map.get("searchField") + "" + " like '%" + map.get("searchWord") + "%'";
// where title like '%제목%';
}
try {
psmt = con.prepareStatement(query);
rs = psmt.executeQuery();
if (rs.next()) {
totalcount = rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
}
return totalcount;
}
// 2. 검색 조건에 맞는 게시물 목록을 반환합니다.
public List<BoardDTO> selectList(Map<String, Object> map) {
List<BoardDTO> bbs = new ArrayList<>();
String query = " select * from board ";
if (map.get("searchWord") != null) {
query += " where " + map.get("searchField") + " like '%" + map.get("searchWord") + "%'";
}
query += " order by num desc ";
try {
psmt = con.prepareStatement(query);
rs = psmt.executeQuery();
while (rs.next()) {
// 이 정보들을 DTO에 넣어준다
BoardDTO dto = new BoardDTO();
// DB 컬럼명
dto.setNum(rs.getString("num"));
dto.setTitle(rs.getString("title"));
dto.setContent(rs.getString("content"));
dto.setPostDate(rs.getDate("postdate"));
dto.setId(rs.getString("id"));
dto.setVisitcount(rs.getString("visitcount"));
// DTO는 가장 최근의 정보만 읽어온다.
// 읽어와서 DTO에 담긴 정보를 다른 곳에 저장해야 목록을 볼 수 있다.
// collection ArayList()에 저장
bbs.add(dto);
}
} catch (Exception e) {
e.printStackTrace();
}
// 목록 데이터가 담긴 bbs를 리턴한다.
return bbs;
}
// 3. 검색 조건에 맞는 게시물 목록을 반환합니다(페이징 기능 지원).
public List<BoardDTO> selectListPage(Map<String, Object> map) {
List<BoardDTO> bbs = new ArrayList<>();
String query = " select * "
+ " from ( "
+ " select rownum rm, p.* "
+ " from ( "
+ " select * "
+ " from board ";
if (map.get("searchWord") != null) {
query += " where " + map.get("searchField") + " like '%" + map.get("searchWord") + "%'";
}
query += " order by num desc "
+ " ) p "
+ " ) "
+ " where rm between ? and ? ";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, map.get("start").toString());
psmt.setString(2, map.get("end").toString());
rs = psmt.executeQuery();
while (rs.next()) {
BoardDTO dto = new BoardDTO();
// DB 컬럼명
dto.setNum(rs.getString("num"));
dto.setTitle(rs.getString("title"));
dto.setContent(rs.getString("content"));
dto.setPostDate(rs.getDate("postdate"));
dto.setId(rs.getString("id"));
dto.setVisitcount(rs.getString("visitcount"));
bbs.add(dto);
}
} catch (Exception e) {
e.printStackTrace();
}
return bbs;
}
// 4. 게시글 데이터를 받아 DB에 추가합니다.
// 실제 데이터를 insert할 수 있는 기능
public int insertWrite(BoardDTO dto) {
// insert 구문이 들어갔는지 확인
int result = 0;
String query = " insert into board " + " (num, title, content, id, visitcount) "
+ " values (seq_board_num.nextval,?,?,?,0) ";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, dto.getTitle());
psmt.setString(2, dto.getContent());
// 로그인한 ID 받아오기 -> session 영역의 정보를 받아온다
psmt.setString(3, dto.getId());
result = psmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
// 5. 지정한 게시물을 찾아 내용을 반환합니다.
public BoardDTO selectView(String num) {
BoardDTO dto = new BoardDTO();
String query = " select B.*, M.name " + " from member M inner join board B " + " on M.id = B.id"
+ " where num = ? ";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, num);
rs = psmt.executeQuery();
if (rs.next()) {
dto.setNum(rs.getString(1));
dto.setTitle(rs.getString(2));
dto.setContent(rs.getString("content"));
dto.setPostDate(rs.getDate("postdate"));
dto.setId(rs.getString("id"));
dto.setVisitcount(rs.getString(6));
dto.setName(rs.getString("name"));
// System.out.println("kkkkkk : " + dto.getId());
}
} catch (Exception e) {
e.printStackTrace();
}
return dto;
}
// 6. 지정한 게시물의 조회수를 1 증가시킵니다.
public void updateVisitCount(String num) {
String query = " update board " + " set visitcount = visitcount + 1 " + " where num = ? ";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, num);
psmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
// 7. 지정한 게시물을 수정합니다.
public int updateEdit(BoardDTO dto) {
int result = 0;
String query = " update board " + " set title = ? , content = ? " + " where num = ? ";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, dto.getTitle());
psmt.setString(2, dto.getContent());
psmt.setString(3, dto.getNum());
result = psmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
// 8. 지정한 게시물을 삭제합니다.
public int deletePost(BoardDTO dto) {
int result = 0;
String query = " delete from board where num = ? ";
try {
psmt = con.prepareStatement(query);
psmt.setString(1, dto.getNum());
result = psmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}