Coding History

국비 지원 IT(웹앱개발) 취업반 강의 44일차 2 (HTML, CSS, JS)

BlackBirdIT 2024. 8. 7. 09:26

페이지를 글 목록 수에 따라서 나누려고 한다.

DB에서 글을 임의로 늘렸고 페이지당 항목 수도 10 15 20 30으로 정할 수 있게 만들었다.

package com.KoreaIT.java.jsp_AM.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import com.KoreaIT.java.jsp_AM.util.DBUtil;
import com.KoreaIT.java.jsp_AM.util.SecSql;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/article/list")
public class ArticleListServlet extends HttpServlet {


    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        // 페이지 번호와 페이지당 항목 수 파라미터
        int page = 1;
        int pageSize = 20; // 기본값

        String pageParam = request.getParameter("page");
        if (pageParam != null && !pageParam.isEmpty()) {
            try {
                page = Integer.parseInt(pageParam);
            } catch (NumberFormatException e) {
                page = 1; // 기본값
            }
        }

        String pageSizeParam = request.getParameter("pageSize");
        if (pageSizeParam != null && !pageSizeParam.isEmpty()) {
            try {
                pageSize = Integer.parseInt(pageSizeParam);
            } catch (NumberFormatException e) {
                pageSize = 20; // 기본값
            }
        }

        // DB 연결
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.out.println("클래스 x");
            e.printStackTrace();
        }

        response.getWriter().append("123");

        String url = "jdbc:mysql://127.0.0.1:3306/AM_JDBC_2024_07?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul";

        String user = "root";
        String password = "1234";

        Connection conn = null;

        try {
            conn = DriverManager.getConnection(url, user, password);
            response.getWriter().append("연결 성공!");

            // 페이징 쿼리
            int offset = (page - 1) * pageSize;
            SecSql sql = SecSql.from("SELECT *");
            sql.append("FROM article");
            sql.append("ORDER BY id DESC");
            sql.append("LIMIT ?", pageSize);
            sql.append("OFFSET ?", offset);

            List<Map<String, Object>> articleRows = DBUtil.selectRows(conn, sql);

            // 전체 게시물 수를 구하는 쿼리
            SecSql countSql = SecSql.from("SELECT COUNT(*) AS total FROM article");
            int totalCount = DBUtil.selectRowIntValue(conn, countSql);

         // 총 페이지 수
            int totalPages = (int) Math.ceil(totalCount / (double) pageSize);

            request.setAttribute("articleRows", articleRows);
            request.setAttribute("currentPage", page);
            request.setAttribute("totalPages", totalPages);
            request.setAttribute("currentPageSize", pageSize);
            request.setAttribute("pageSizes", new int[]{10, 15, 20, 30});

            request.getRequestDispatcher("/jsp/article/list.jsp").forward(request, response);



        } catch (SQLException e) {
            System.out.println("에러 1 : " + e);
        } finally {
            try {
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }

}

서블릿은 이렇게 수정했고 JSP는

<%@page import="java.util.List"%>
<%@page import="java.util.Map"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
List<Map<String, Object>> articleRows = (List<Map<String, Object>>) request.getAttribute("articleRows");
int currentPage = (Integer) request.getAttribute("currentPage");
int totalPages = (Integer) request.getAttribute("totalPages");
int currentPageSize = (Integer) request.getAttribute("currentPageSize");
int[] pageSizes = (int[]) request.getAttribute("pageSizes");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시물 목록</title>
</head>
<body>

    <h2>게시물 목록</h2>

    <a href="../home/main">메인 페이지로 </a>

    <!-- 페이지개수 정하기  -->

    <form method="get" action="">
        <label for="pageSize">페이지당 항목 수:</label>
        <select id="pageSize" name="pageSize" onchange="this.form.submit()">
            <% for (int size : pageSizes) { %>
                <option value="<%= size %>" <%= (size == currentPageSize) ? "selected" : "" %>><%= size %></option>
            <% } %>
        </select>
    </form>

    <table style="border-collapse: collapse; border-color: green;"
        border="1px">
        <thead>
            <tr>
                <th>번호</th>
                <th>날짜</th>
                <th>제목</th>
                <th>내용</th>
                <th>삭제</th>
            </tr>
        </thead>
        <tbody>
            <%
            for (Map<String, Object> articleRow : articleRows) {
            %>
            <tr style="text-align: center;">
                <td><%=articleRow.get("id")%></td>
                <td><%=articleRow.get("regDate")%></td>
                <td><%=articleRow.get("title")%></td>
                <td><%=articleRow.get("body")%></td>
                <td><a href="doDelete?id=<%=articleRow.get("id")%>">del</a></td>
            </tr>
            <%
            }
            %>
        </tbody>
    </table>

    <div>
        <% if (currentPage > 1) { %>
            <a href="?page=<%=currentPage - 1%>&pageSize=<%=currentPageSize%>">이전</a>
        <% } %>
        <span>Page <%=currentPage%> of <%=totalPages%></span>
        <% if (currentPage < totalPages) { %>
            <a href="?page=<%=currentPage + 1%>&pageSize=<%=currentPageSize%>">다음</a>
        <% } %>
    </div>

    <!--     <ul> -->
    <%--         <% --%>
    <%--//         for (Map<String, Object> articleRow : articleRows) {--%>
    <%--         %> --%>
    <%--         <li><a href="detail?id=<%=articleRow.get("id")%>"><%=articleRow.get("id")%>번, --%>
    <%--                 <%=articleRow.get("regDate")%>,<%=articleRow.get("title")%>,<%=articleRow.get("body")%></a></li> --%>
    <%--         <% --%>
    <%--//         }--%>
    <%--         %> --%>
    <!--     </ul> -->


</body>
</html>

이렇게 수정했다.

보는 바와 같이 잘 구현되었다 다음과 이전으로도 잘 간다. 20개를 보고 싶으면 20을 클릭하면 이렇게 스무개를 보여준다.

그럼 아래의 Page의 개수도 창 개수에 맞게 줄어든다.

그런데 글이 많아질 경우 페이지도 많아질텐데 계속 다음과 이전만 누를 수는 없을 것 같다는 생각이 들어서 숫자로 클릭할 수 있게 변경하고 싶어졌다.

<div>
        <% if (startPage > 1) { %>
            <a href="?page=1&pageSize=<%=currentPageSize%>">1</a>
            <% if (startPage > 2) { %>
                <span>...</span>
            <% } %>
        <% } %>
        <% for (int i = startPage; i <= endPage; i++) { %>
            <% if (i == currentPage) { %>
                <span><%=i%></span>
            <% } else { %>
                <a href="?page=<%=i%>&pageSize=<%=currentPageSize%>"><%=i%></a>
            <% } %>
        <% } %>
        <% if (endPage < totalPages) { %>
            <% if (endPage < totalPages - 1) { %>
                <span>...</span>
            <% } %>
            <a href="?page=<%=totalPages%>&pageSize=<%=currentPageSize%>"><%=totalPages%></a>
        <% } %>
    </div>

    <form method="get" action="">
        <label for="gotoPage">페이지로 이동:</label>
        <input type="number" id="gotoPage" name="page" min="1" max="<%=totalPages%>" value="<%=currentPage%>">
        <input type="hidden" name="pageSize" value="<%=currentPageSize%>">
        <button type="submit">이동</button>
    </form>

html구조를 이렇게 바꾸었고 웹상에서는 이렇게 보인다.

페이지로 이동 텝에서 숫자를 입력하면 해당 페이지로 넘어간다.

다음시간부터는 write, modify를 할 것 같다.