ํฌ์ŠคํŠธ

๐Ÿง‘โ€๐Ÿ’ป ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ - ํšŒ์›์ œ ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ(JAVA)

JWT ์ธ์ฆ ๊ธฐ๋ฐ˜ ํšŒ์›์ œ ๊ฒŒ์‹œํŒ ๊ตฌํ˜„ Project ์ž…๋‹ˆ๋‹ค.

๐Ÿง‘โ€๐Ÿ’ป ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ - ํšŒ์›์ œ ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ(JAVA)

JAVA ํšŒ์›์ œ ๊ฒŒ์‹œํŒ ๊ตฌํ˜„


1. ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

ใ…ค์ด ํ”„๋กœ์ ํŠธ๋Š” JAVA๋กœ ๊ตฌํ˜„๋œ ํšŒ์›์ œ ๊ฒŒ์‹œํŒ ์‚ฌ์ดํŠธ์ž…๋‹ˆ๋‹ค.

ใ…ค์‚ฌ์šฉ์ž๋Š” ํšŒ์›๊ฐ€์ž…์„ ํ†ตํ•ด ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ, ์กฐํšŒ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ใ…ค

๊ฐœ๋ฐœํ™˜๊ฒฝ Eclipse / JDK 17
์„œ๋ฒ„ Apache Tomcat/10.1.31
๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค Oracle Database 18c Express Edition

2. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

์ƒ์„ธ ๊ตฌ์กฐ๋Š” ํŽ˜์ด์ง€ ์ƒ๋‹จ์˜ ๊นƒํ—ˆ๋ธŒ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”

๐Ÿ“src
  โ””โ”€โ”€๐Ÿ“main
        โ””โ”€โ”€๐Ÿ“java
              โ””โ”€โ”€๐Ÿ“controller - ๐Ÿ“„๊ฒŒ์‹œํŒ CRUD, ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž…์šฉ ์ปจํŠธ๋กค๋Ÿฌ
              โ””โ”€โ”€๐Ÿ“filter -๐Ÿ“„ํ† ํฐ ๊ธฐ๋ฐ˜ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ฒ˜๋ฆฌ ํ•„ํ„ฐ
              โ””โ”€โ”€๐Ÿ“listener -๐Ÿ“„์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘, ์ข…๋ฃŒ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฆฌ์Šค๋„ˆ
              โ””โ”€โ”€๐Ÿ“model - ๐Ÿ“„ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ๋ฐ UI ์ƒ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค
              โ””โ”€โ”€๐Ÿ“resources
              โ””โ”€โ”€๐Ÿ“service
        โ””โ”€โ”€๐Ÿ“webapp
              โ””โ”€โ”€๐Ÿ“bbspage - ๐Ÿ“„๊ฒŒ์‹œํŒ ํŽ˜์ด์ง€ CRUD ๊ด€๋ จ ๋กœ์ง 
              โ””โ”€โ”€๐Ÿ“connectionpool
              โ””โ”€โ”€๐Ÿ“META_INF
              โ””โ”€โ”€๐Ÿ“page - ๐Ÿ“„ํšŒ์›๊ฐ€์ž… , ๋กœ๊ทธ์ธ , ํ™ˆ ํŽ˜์ด์ง€ ๊ด€๋ จ ๋กœ์ง
              โ””โ”€โ”€๐Ÿ“template 
              โ””โ”€โ”€๐Ÿ“WEB-INF

3. ์ฃผ์š” ์ฝ”๋“œ

์ƒ์„ธ ์ฝ”๋“œ๋Š” ํŽ˜์ด์ง€ ์ƒ๋‹จ์˜ ๊นƒํ—ˆ๋ธŒ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”

(1) ๋กœ๊ทธ์ธ
LoginController.java

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋ธ”๋ฆฟ์œผ๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์˜ ์„ธ์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์„ฑ๊ณต์ ์ธ ๋กœ๊ทธ์ธ ์‹œ ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•˜์—ฌ ์ฟ ํ‚ค์™€ ์„ธ์…˜์— ์ €์žฅํ•˜๊ณ , ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ์ง€์ •๋œ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค.

์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

      
      
      
  @WebServlet("/LoginController")
  public class LoginController extends HttpServlet {
      private static final long serialVersionUID = 1L;

      // POST ์š”์ฒญ ์ฒ˜๋ฆฌ
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          request.setCharacterEncoding("UTF-8");  // ํ•œ๊ธ€ ์ธ์ฝ”๋”ฉ ์„ค์ •

          String username = request.getParameter("username");  // ์ž…๋ ฅ๋ฐ›์€ ์•„์ด๋””
          String password = request.getParameter("password");  // ์ž…๋ ฅ๋ฐ›์€ ๋น„๋ฐ€๋ฒˆํ˜ธ

          // ๊ฐ„๋‹จํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ (์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธ)
          if (username == null || username.trim().isEmpty() || password == null || password.isEmpty()) {
              handleError(request, response, "์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ชจ๋‘ ์ž…๋ ฅํ•˜์„ธ์š”");
              return;
          }

          UserDAO userDAO = new UserDAO();  // ์‚ฌ์šฉ์ž ๊ฒ€์ฆ์„ ์œ„ํ•œ UserDAO ๊ฐ์ฒด ์ƒ์„ฑ

          // ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ
          if (userDAO.validateUser(username, password)) {
              // ์ธ์ฆ ์„ฑ๊ณต ์‹œ ํ† ํฐ ๋ฐœ๊ธ‰
              String token = userDAO.issueToken(username);  // ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐœ๊ธ‰ํ•  ํ† ํฐ ์ƒ์„ฑ
              Cookie tokenCookie = new Cookie("token", token);  // ํ† ํฐ์„ ์ฟ ํ‚ค๋กœ ์ƒ์„ฑ
              tokenCookie.setMaxAge(60 * 60 * 24 * 7); // ์ฟ ํ‚ค ์œ ํšจ๊ธฐ๊ฐ„ ์„ค์ • (7์ผ)
              response.addCookie(tokenCookie);  // ์ฟ ํ‚ค๋ฅผ ์‘๋‹ต์— ์ถ”๊ฐ€

            // HttpSession์„ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •๋ณด ์ €์žฅ
            HttpSession session = request.getSession();  // ์„ธ์…˜ ์ƒ์„ฑ
            request.getSession().setAttribute("token", token);  // ์„ธ์…˜์— ํ† ํฐ ์ €์žฅ
            session.setAttribute("token", token);  // ์„ธ์…˜์— ํ† ํฐ ์ €์žฅ
            session.setAttribute("username", username);  // ์„ธ์…˜์— ์‚ฌ์šฉ์ž ์ด๋ฆ„ ์ €์žฅ

            // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ํŽ˜์ด์ง€ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
            response.sendRedirect(request.getContextPath() + "/page/LoginOk.jsp");
        } else {
            // ์ธ์ฆ ์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ
            handleError(request, response, "์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค");
        }
    }

    // ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์ „๋‹ฌํ•˜๋Š” ๋ฉ”์†Œ๋“œ
    private void handleError(HttpServletRequest request, HttpServletResponse response, String message) throws ServletException, IOException {
        request.setAttribute("errorMessage", message);  // ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์„ค์ •
        request.getRequestDispatcher("/page/Login.jsp").forward(request, response);  // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ํฌ์›Œ๋“œ
    }
}
      
    
LogoutController.java

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋ธ”๋ฆฟ์œผ๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒ์„ ์š”์ฒญํ•˜๋ฉด ์„ธ์…˜๊ณผ ์ฟ ํ‚ค๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.

POST ์š”์ฒญ์—์„œ ์„ธ์…˜์„ ๋ฌดํšจํ™”ํ•˜๊ณ , "token"์ด๋ผ๋Š” ์ด๋ฆ„์˜ ์ฟ ํ‚ค๋ฅผ ์‚ญ์ œํ•œ ํ›„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

      
      
      
  @WebServlet("/LogoutController")
  public class LogoutController extends HttpServlet {
      private static final long serialVersionUID = 1L;

      // POST ์š”์ฒญ ์ฒ˜๋ฆฌ
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          // ์„ธ์…˜ ๋ฌดํšจํ™”
          request.getSession().invalidate();  // ์„ธ์…˜ ์ดˆ๊ธฐํ™”

          // "token" ์ฟ ํ‚ค ์‚ญ์ œ
          Cookie[] cookies = request.getCookies();  // ์š”์ฒญ์—์„œ ๋ชจ๋“  ์ฟ ํ‚ค๋ฅผ ๊ฐ€์ ธ์˜ด
          if (cookies != null) {
              for (Cookie cookie : cookies) {
                  if (cookie.getName().equals("token")) {  // "token" ์ฟ ํ‚ค ์ฐพ๊ธฐ
                      cookie.setMaxAge(0);  // ์ฟ ํ‚ค ์œ ํšจ๊ธฐ๊ฐ„์„ 0์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์‚ญ์ œ
                      response.addCookie(cookie);  // ์‚ญ์ œ๋œ ์ฟ ํ‚ค๋ฅผ ์‘๋‹ต์— ์ถ”๊ฐ€
                      break;  // ๋” ์ด์ƒ ๋ฐ˜๋ณตํ•  ํ•„์š” ์—†์Œ
                  }
              }
          }

          // ๋กœ๊ทธ์•„์›ƒ ํ›„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
          response.sendRedirect(request.getContextPath() + "/page/Login.jsp");  // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™
      }

      // GET ์š”์ฒญ์„ POST ์š”์ฒญ์œผ๋กœ ์ฒ˜๋ฆฌ
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          doPost(request, response);  // GET ์š”์ฒญ์€ POST ์š”์ฒญ์œผ๋กœ ์ฒ˜๋ฆฌ
      }
  }
      
    
Login.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋กœ๊ทธ์ธ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•˜๋Š” JSP ๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํผ ์ œ์ถœ ์‹œ, ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ `LoginController`๋กœ ์ „์†กํ•˜๋ฉฐ, ๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.




  <%@ 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>
      <jsp:include page="/template/Config.jsp" />
      <title>Login</title> // ํŽ˜์ด์ง€ ์ œ๋ชฉ ์„ค์ •
      <script>
          // ํŽ˜์ด์ง€ ๋กœ๋”ฉ ํ›„, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ๊ฒฝ๊ณ ์ฐฝ์œผ๋กœ ํ‘œ์‹œ
          document.addEventListener('DOMContentLoaded', function() {
              var errorMsg = '<%= request.getAttribute("errorMsg") %>'; // request ๊ฐ์ฒด์—์„œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๊ฐ€์ ธ์˜ค๊ธฐ
              if (errorMsg && errorMsg !== 'null') {
                  alert(errorMsg);  // ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์กด์žฌ ์‹œ ๊ฒฝ๊ณ ์ฐฝ์œผ๋กœ ํ‘œ์‹œ
              }
          });
      </script>
  </head>
  <body>
    <div class="container">
        <div class="container-fluid">
            <jsp:include page="/template/Header.jsp" />
            <div class="p-5 bg-success text-white">
                <h1 style="font-weight: bold;">๋กœ๊ทธ์ธ</h1>
            </div>
            <fieldset class="border rounded-3 p-3 text-center mt-3 mb-3">
                <legend class="float-none w-auto px-3" style="font-weight: bold;">๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”</legend> // ๋กœ๊ทธ์ธ ํผ ์ œ๋ชฉ
                <form class="needs-validation" action="${pageContext.request.contextPath}/LoginController" method="post">
                    <div class="row justify-content-center">
                        <div class="col-md-8">
                            <div class="row mb-3">
                                <div class="col-md-4 mb-2 mt-5 d-flex align-items-center justify-content-md-end">
                                    <label for="username" class="form-label" style="font-weight: bold;">์•„์ด๋””</label> // ์•„์ด๋”” ์ž…๋ ฅ ํ•„๋“œ ๋ผ๋ฒจ
                                </div>
                                <div class="col-md-6 mb-3 mt-5">
                                    <input type="text" class="form-control" id="username" placeholder="์•„์ด๋”” ์ž…๋ ฅ" name="username" value="${param.username}"> // ์•„์ด๋”” ์ž…๋ ฅ ํ•„๋“œ
                                </div>
                            </div>

                            <div class="row mb-3">
                                <div class="col-md-4 mb-2 mt-3 d-flex align-items-center justify-content-md-end">
                                    <label for="password" class="form-label" style="font-weight: bold;">๋น„๋ฐ€๋ฒˆํ˜ธ</label> // ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํ•„๋“œ ๋ผ๋ฒจ
                                </div>
                                <div class="col-md-6 mb-3 mt-3">
                                    <input type="password" class="form-control" id="password" placeholder="๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ" name="password"> // ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํ•„๋“œ
                                </div>
                            </div>

                            <div class="row mb-3">
                                <div class="col-md-12">
                                    <button type="submit" class="btn btn-dark">๋กœ๊ทธ์ธ</button> // ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ
                                </div>
                            </div>

                            <c:if test="${not empty errorMessage}">
                                <div class="row mb-3">
                                    <div class="col-md-12 d-flex justify-content-center">
                                        <div class="alert alert-danger" style="max-width: 50%; padding: 20px;">
                                            ${errorMessage}  // ๋กœ๊ทธ์ธ ์‹คํŒจ ์‹œ, ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œ
                                        </div>
                                    </div>
                                </div>
                            </c:if>

                        </div>
                    </div>
                </form>
            </fieldset>
            <jsp:include page="/template/Footer.jsp" />
        </div>
    </div>
  </body>
  </html>
      
LoginOk.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ์‚ฌ์šฉ์ž์—๊ฒŒ ํ™˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜๋Š” JSP ์ž…๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ, ์„ธ์…˜์—์„œ ์‚ฌ์šฉ์ž์˜ ํ† ํฐ์„ ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•˜๋ฉฐ, ์‚ฌ์šฉ์ž์—๊ฒŒ ํ™˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.




  <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> // ํŽ˜์ด์ง€์˜ ์ธ์ฝ”๋”ฉ ๋ฐ ์–ธ์–ด ์„ค์ •
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> // JSTL ์ฝ”์–ด ํƒœ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํฌํ•จ

  <!DOCTYPE html>
  <html>
  <head>
      <jsp:include page="/template/Config.jsp"/>
      <title>LoginOk.jsp</title>
      <script>
          // ํด๋ผ์ด์–ธํŠธ ์ธก JavaScript ์ฝ”๋“œ ์ž‘์„ฑ
          var token = '${sessionScope.token}'; // ์„ธ์…˜์—์„œ ํ† ํฐ ๊ฐ’์„ ๊ฐ€์ ธ์˜ด
          localStorage.setItem('token', token); // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ํ† ํฐ ์ €์žฅ
      </script>
  </head>
  <body>
      <div class="container">
          <div class="container-fluid">
              <jsp:include page="/template/Header.jsp"/>
              
              <!-- ์ปจํ…์ธ  ์‹œ์ž‘ -->
              <div class="p-5 bg-success text-white">
                  <h1 style="font-weight:bold;">๋กœ๊ทธ์ธ ์„ฑ๊ณต</h1> // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
              </div>
              
              <fieldset class="border rounded-3 p-3 text-center mt-3 mb-3">
                  <h3 class="display-6" style="font-weight:bold;">${sessionScope.username}๋‹˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!</h3> // ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅ
                  
                  <div class="row mt-4">
                      <div class="col-md-12">
                          <h5>์ƒ๋‹จ ๋ฉ”๋‰ด๋ฅผ ํ†ตํ•ด ์ด๋™ํ•ด์ฃผ์„ธ์š”</h5>
                      </div>
                  </div>
              </fieldset>        
              <!-- ์ปจํ…์ธ  ๋ -->
              
              <jsp:include page="/template/Footer.jsp"/>      
          </div><!-- container-fluid -->
      </div><!-- container -->
      
      <script>
          document.getElementById('boardBtn').addEventListener('click', function() {
              window.location.href = '${pageContext.request.contextPath}/BoardController';  // ๊ฒŒ์‹œํŒ ํŽ˜์ด์ง€๋กœ ์ด๋™
          });
      </script>
  </body>
  </html>

(2) ํšŒ์›๊ฐ€์ž…
SignUpController.java

์•„๋ž˜ ์ฝ”๋“œ๋Š” ํšŒ์›๊ฐ€์ž…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์„œ๋ธ”๋ฆฟ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ํšŒ์›๊ฐ€์ž… ํผ์„ ์ œ์ถœํ•˜๋ฉด ์ด ์„œ๋ธ”๋ฆฟ์ด ํ˜ธ์ถœ๋˜์–ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์™€ ์ค‘๋ณต ๊ฒ€์‚ฌ ํ›„, ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.




  @WebServlet("/SignUpController") // ์ด ์„œ๋ธ”๋ฆฟ์€ "/SignUpController" URL์— ๋งคํ•‘
  public class SignUpController extends HttpServlet {
      private static final long serialVersionUID = 1L; // ์ง๋ ฌํ™” ID ์„ค์ •

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          request.setCharacterEncoding("UTF-8"); // ์š”์ฒญ์˜ ๋ฌธ์ž ์ธ์ฝ”๋”ฉ์„ UTF-8๋กœ ์„ค์ •

          // ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„์˜ด
          String username = request.getParameter("username"); // ์‚ฌ์šฉ์ž ์•„์ด๋””
          String password = request.getParameter("password"); // ์‚ฌ์šฉ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ
          String passwordConfirm = request.getParameter("passwordConfirm"); // ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ
          String gender = request.getParameter("gender"); // ์„ฑ๋ณ„
          String[] interests = request.getParameterValues("interests"); // ๊ด€์‹ฌ์‚ฌ
          String grade = request.getParameter("grade"); // ํ•™๋ ฅ
          String self = request.getParameter("self"); // ์ž๊ธฐ์†Œ๊ฐœ
          String token = request.getParameter("token"); // ํ† ํฐ

          // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
          if (username == null || username.trim().isEmpty()) { // ์•„์ด๋”” ์ž…๋ ฅ ํ™•์ธ
              handleError(request, response, "์•„์ด๋””๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”");
              return;
          }

          if (password == null || password.isEmpty()) { // ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํ™•์ธ
              handleError(request, response, "๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”");
              return;
          }

          if (!password.equals(passwordConfirm)) { // ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ ์ผ์น˜ ํ™•์ธ
              handleError(request, response, "๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋‹ค์‹œ ํ•œ๋ฒˆ ํ™•์ธํ•ด ์ฃผ์„ธ์š”");
              return;
          }

          if (gender == null || gender.isEmpty()) { // ์„ฑ๋ณ„ ์ž…๋ ฅ ํ™•์ธ
              handleError(request, response, "์„ฑ๋ณ„์„ ์„ ํƒํ•˜์„ธ์š”");
              return;
          }

          if (interests == null || interests.length < 2) { // ๊ด€์‹ฌ์‚ฌ 2๊ฐœ ์ด์ƒ ์„ ํƒ ํ™•์ธ
              handleError(request, response, "๊ด€์‹ฌ์‚ฌํ•ญ์€ 2๊ฐœ ์ด์ƒ ์„ ํƒํ•˜์„ธ์š”");
              return;
          }

          if (grade == null || grade.isEmpty()) { // ํ•™๋ ฅ ์ž…๋ ฅ ํ™•์ธ
              handleError(request, response, "ํ•™๋ ฅ์„ ์„ ํƒํ•˜์„ธ์š”");
              return;
          }

          if (self == null || self.trim().isEmpty()) { // ์ž๊ธฐ์†Œ๊ฐœ ์ž…๋ ฅ ํ™•์ธ
              handleError(request, response, "์ž๊ธฐ์†Œ๊ฐœ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”");
              return;
          }

          // ์ค‘๋ณต ์ฒดํฌ
          UserDAO userDAO = new UserDAO();
          if (userDAO.checkUsernameExists(username)) { // ์•„์ด๋”” ์ค‘๋ณต ์ฒดํฌ
              handleError(request, response, "์ค‘๋ณต๋œ ์•„์ด๋””๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์•„์ด๋””๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”");
              return;
          }

          // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๋ชจ๋‘ ํ†ต๊ณผํ•˜๋ฉด UserDTO ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ €์žฅ
          UserDTO user = new UserDTO(username, password, passwordConfirm, gender, interests, grade, self, token);

          if (userDAO.saveUser(user)) { // ์‚ฌ์šฉ์ž ์ €์žฅ ์„ฑ๊ณต
            request.setAttribute("username", username); // ์„ฑ๊ณต ์‹œ ์‚ฌ์šฉ์ž ์ด๋ฆ„ ์ „๋‹ฌ
              request.getRequestDispatcher("/page/SignUpOk.jsp").forward(request, response); // ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต ํŽ˜์ด์ง€๋กœ ํฌ์›Œ๋”ฉ
          } else { // ์‚ฌ์šฉ์ž ์ €์žฅ ์‹คํŒจ
              handleError(request, response, "ํšŒ์›๊ฐ€์ž…์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.");
          }
      }

      // ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์ฒ˜๋ฆฌ ๋ฉ”์„œ๋“œ
      private void handleError(HttpServletRequest request, HttpServletResponse response, String message) throws ServletException, IOException {
          request.setAttribute("modalMessage", message); // ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์š”์ฒญ์— ์ €์žฅ
          request.getRequestDispatcher("/page/SignUp.jsp").forward(request, response); // ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€๋กœ ํฌ์›Œ๋”ฉ
      }
  }

SignUp.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ์‚ฌ์šฉ์ž ํšŒ์›๊ฐ€์ž… JSP ์ž…๋‹ˆ๋‹ค.

ํšŒ์›๊ฐ€์ž… ํผ์€ ์‚ฌ์šฉ์ž ์ด๋ฆ„, ์ด๋ฉ”์ผ, ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ , ์ œ์ถœ ์‹œ 'signup.do'๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

ํ•„์ˆ˜ ์ž…๋ ฅ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.




  <%@page import="java.util.Arrays"%>
  <%@ 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>
      <jsp:include page="/template/Config.jsp" />
      <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
      <title>SignUp.jsp</title>
  </head>
  <body>

      <div class="container">
          <div class="container-fluid">
              <jsp:include page="/template/Header.jsp" />

              <!-- ํšŒ์›๊ฐ€์ž… ์–‘์‹ ์‹œ์ž‘ -->
              <div class="p-5 bg-success text-white mb-3">
                  <h1 style="font-weight: bold;">ํšŒ์›๊ฐ€์ž…</h1>
              </div>
              <form action="signup.do" method="post" class="needs-validation" novalidate> // ํšŒ์›๊ฐ€์ž… ํผ ์‹œ์ž‘
                  <div class="form-group"> // ์‚ฌ์šฉ์ž ์ด๋ฆ„ ์ž…๋ ฅ๋ž€
                      <label for="username">์‚ฌ์šฉ์ž ์ด๋ฆ„</label>
                      <input type="text" class="form-control" id="username" name="username" required>
                      <div class="invalid-feedback">์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.</div>
                  </div&gt>

                  <div class="form-group"> // ์ด๋ฉ”์ผ ์ž…๋ ฅ๋ž€
                      <label for="email">์ด๋ฉ”์ผ</label>
                      <input type="email" class="form-control" id="email" name="email" required>
                      <div class="invalid-feedback">์œ ํšจํ•œ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”.</div>
                  </div&gt>

                  <div class="form-group"> // ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ๋ž€
                      <label for="password">๋น„๋ฐ€๋ฒˆํ˜ธ</label>
                      <input type="password" class="form-control" id="password" name="password" required>
                      <div class="invalid-feedback">๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.</div>
                  </div>

                  <button type="submit" class="btn btn-primary mt-3">ํšŒ์›๊ฐ€์ž…</button> // ์ œ์ถœ ๋ฒ„ํŠผ
              </form>
              <!-- ํšŒ์›๊ฐ€์ž… ์–‘์‹ ๋ -->

          </div>
      </div>

  </body>
  </html>

(3) ๊ฒŒ์‹œ๊ธ€ CRUD
WriteController.java

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ ์ฒ˜๋ฆฌํ•˜๋Š” WriteController ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ์ƒํƒœ์ผ ๊ฒฝ์šฐ ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ๋ฐ›์•„ ๊ฒŒ์‹œ๊ธ€์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์ด ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์ด์ „ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.




  @WebServlet("/WriteController") // URL ๋งคํ•‘
  public class WriteController extends HttpServlet { 
      private static final long serialVersionUID = 1L;

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          HttpSession session = request.getSession(); // ์„ธ์…˜ ๊ฐ€์ ธ์˜ค๊ธฐ
          String username = (String) session.getAttribute("username"); // ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ
          String token = (String) session.getAttribute("token"); // ํ† ํฐ ๊ฐ€์ ธ์˜ค๊ธฐ

          response.setContentType("text/html; charset=UTF-8");
          PrintWriter out = response.getWriter();

          // ์‚ฌ์šฉ์ž ์•„์ด๋””๊ฐ€ ์—†์œผ๋ฉด ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™
          if (username == null || username.isEmpty() || token == null || token.isEmpty()) {
              response.sendRedirect("/YoonSeongBinProj2/page/Login.jsp"); // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ
          } else {
              // ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ
              String title = request.getParameter("title");
              String content = request.getParameter("content");

              // ์ œ๋ชฉ์ด๋‚˜ ๋‚ด์šฉ์ด ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ
              if (title == null || title.trim().isEmpty() || content == null || content.trim().isEmpty()) {
                  out.println("<script>");
                  out.println("alert('์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.');"); // ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€
                  out.println("history.back();"); // ์ด์ „ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ธฐ
                  out.println("</script>");
              } else {
                  // ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก ๋กœ์ง
                  ServletContext application = getServletContext();
                  BbsDTO item = new BbsDTO(); // ์ƒˆ๋กœ์šด ๊ฒŒ์‹œ๊ธ€ ๊ฐ์ฒด ์ƒ์„ฑ
                  item.setContent(content); // ๋‚ด์šฉ ์„ค์ •
                  item.setTitle(title); // ์ œ๋ชฉ ์„ค์ •
                  item.setUsername(username); // ์‚ฌ์šฉ์ž ์ด๋ฆ„ ์„ค์ •

                  BbsDAO dao = new BbsDAO(application); // DAO ๊ฐ์ฒด ์ƒ์„ฑ
                  int affected = dao.insert(item); // ๊ฒŒ์‹œ๊ธ€ ์‚ฝ์ž…
                  dao.close(); // DAO ์ข…๋ฃŒ

                  if (affected > 0) {
                      out.println("<script>");
                      out.println("alert('๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค');"); // ๋“ฑ๋ก ์™„๋ฃŒ ๋ฉ”์‹œ์ง€
                      out.println("location.href='/YoonSeongBinProj2/bbspage/BbsList.jsp';"); // ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ํŽ˜์ด์ง€๋กœ ์ด๋™
                      out.println("</script>");
                  } else {
                      out.println("<script>");
                      out.println("alert('๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”');"); // ์‹คํŒจ ๋ฉ”์‹œ์ง€
                      out.println("history.back();"); // ์ด์ „ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ธฐ
                      out.println("</script>");
                  }
              }
          }
      }

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          doPost(request, response); // doPost ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
      }
  }

BbsDAO.java

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œํŒ DAO(Data Access Object) ์ž…๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•ด์„œ CRUD ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์—…๋ฌด ์ฒ˜๋ฆฌ ๋กœ์ง์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.




  public class BbsDAO2 implements DAOService<BbsDTO> {

    // ํ•„๋“œ
    private Connection conn;
    private ResultSet rs;
    private PreparedStatement psmt;

    // ์ƒ์„ฑ์ž
    public BbsDAO2(ServletContext context) {
        try {
            Context initContext = new InitialContext();
            Context envContext = (Context) initContext.lookup("java:comp/env");
            DataSource dataSource = (DataSource) envContext.lookup("jdbc/ICTUSER");
            conn = dataSource.getConnection();
        } catch (NamingException | SQLException e) {
            e.printStackTrace();
        }
    }

    // ์ž์› ๋ฐ˜๋‚ฉ์šฉ

    @Override
    public void close() {
        try {
            if (rs != null) rs.close();
            if (psmt != null) psmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {}
    }

    //์ „์ฒด ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ

    /*
    * ํŽ˜์ด์ง• ๋กœ์ง ์ถ”๊ฐ€ํ•˜๊ธฐ
    * DAO์—์„œ ํ•  ์ผ
    * 1. ์ „์ฒด ๋ชฉ๋ก ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ๊ฐ„ ์ฟผ๋ฆฌ ํ˜น์€ RANK() ํ•จ์ˆ˜๋กœ ๋ณ€๊ฒฝ
    * 2. ์ด ๋ ˆ์ฝ”๋“œ ์ˆ˜ ๊ตฌํ•˜๋Š” ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€    
    * JSP์—์„œ๋Š” 
    * List.jsp์— ํŽ˜์ด์ง• ๊ด€๋ จ ์ฝ”๋“œ ์ถ”๊ฐ€
    */

    public List<BbsDTO> findAll(Map<String, String> map) {
        List<BbsDTO> items = new ArrayList<>();

        String sql = "SELECT b.id, b.title, b.content, b.hitcount, b.postdate, b.username "
                  + "FROM bbs b ";

        // ๊ฒ€์ƒ‰ ์กฐ๊ฑด ์ถ”๊ฐ€
        if (map.get("searchColumn") != null) {
            if ("username".equals(map.get("searchColumn"))) {
                sql += "WHERE b.username LIKE '%" + map.get("searchWord") + "%' ";
            } else {
                sql += "WHERE " + map.get("searchColumn") + " LIKE '%" + map.get("searchWord") + "%' ";
            }
        }

        sql += "ORDER BY b.id DESC";

        try {
            psmt = conn.prepareStatement(sql);
            rs = psmt.executeQuery();

            while (rs.next()) {
                BbsDTO item = new BbsDTO();
                item.setId(rs.getInt("id"));
                item.setTitle(rs.getString("title"));
                item.setContent(rs.getString("content"));
                item.setHitCount(rs.getInt("hitcount"));
                item.setPostDate(rs.getDate("postdate"));
                item.setUsername(rs.getString("username"));

                items.add(item);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // ์ž์› ํ•ด์ œ
            close();
        }

        return items;
    }

    // ์ด ๋ ˆ์ฝ”๋“œ ์ˆ˜ ์–ป๊ธฐ์šฉ
    @Override
    public int getTotalRecordCount(Map<String,String> map) {
      int totalRecordCount=0;
      String sql="SELECT COUNT(*) FROM bbs b JOIN users u ON b.username=u.username ";
      // ๊ฒ€์ƒ‰์‹œ ์•„๋ž˜ ์ฟผ๋ฆฌ ์ถ”๊ฐ€
      if(map !=null && map.get("searchColumn") !=null) {
        sql+=" WHERE "+map.get("searchColumn") + " LIKE '%"+map.get("searchWord")+"%' ";
      }
      try {
        psmt = conn.prepareStatement(sql);
        rs = psmt.executeQuery();
        rs.next();
        totalRecordCount= rs.getInt(1);
      }
      catch(SQLException e) {e.printStackTrace();}
      return totalRecordCount;
    }

    // ์ƒ์„ธ๋ณด๊ธฐ์šฉ - ๋ ˆ์ฝ”๋“œ ํ•˜๋‚˜ ์กฐํšŒ
    @Override
    public BbsDTO findById(String ... params) {
      BbsDTO item=null;
      
      try {
        // ๋ชฉ๋ก์—์„œ ๋„˜์–ด์˜จ ๊ฒฝ์šฐ์—๋งŒ ์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€
        if(params.length >=2 && params[1].toUpperCase().startsWith("BBSLIST")) {
          psmt = conn.prepareStatement("UPDATE bbs SET hitcount= hitcount+1 WHERE id=?");
          psmt.setString(1, params[0]);
          psmt.executeUpdate();
        }
          
        // ๋ ˆ์ฝ”๋“œ ํ•˜๋‚˜ ์กฐํšŒ
        psmt = conn.prepareStatement("SELECT b.*,name FROM bbs b JOIN users u ON b.username=u.username WHERE id=?");
        psmt.setString(1, params[0]);
        rs = psmt.executeQuery();
        if(rs.next()) {
          item = new BbsDTO();
          item.setContent(rs.getString(4));
          item.setHitCount(rs.getInt(5));
          item.setId(rs.getInt(1));
          item.setPostDate(rs.getDate(6));
          item.setTitle(rs.getString(3));
          item.setUsername(rs.getString(2));
        }
      }
      catch(SQLException e) {e.printStackTrace();}
      return item;
    }

    // ์ด์ „๊ธ€, ๋‹ค์Œ๊ธ€ ์กฐํšŒ
    public Map<String, BbsDTO> prevNext(String curentId){
      Map<String, BbsDTO> map = new HashMap<>();
      try {
        // ์ด์ „๊ธ€ ์–ป๊ธฐ
        psmt = conn.prepareStatement("SELECT id,title FROM bbs WHERE id=(SELECT MAX(id) FROM bbs WHERE id < ?)");
        psmt.setString(1,curentId);
        rs = psmt.executeQuery();
        if(rs.next()) {
          map.put("PREV", new BbsDTO(rs.getLong(1), null, rs.getString(2), null, 0, null));
        }
        
        // ๋‹ค์Œ๊ธ€ ์–ป๊ธฐ
        psmt = conn.prepareStatement("SELECT id,title FROM bbs WHERE id=(SELECT MIN(id) FROM bbs WHERE id > ?)");
        psmt.setString(1,curentId);
        rs = psmt.executeQuery();
        if(rs.next()) {
          map.put("NEXT", new BbsDTO(rs.getLong(1), null, rs.getString(2), null, 0, null));
        }
        
      }
      catch(SQLException e) {e.printStackTrace();}
      
      return map;
    }    
    
    // ์ž…๋ ฅ์šฉ
    @Override
    public int insert(BbsDTO dto) {
      int affected=0;
      try {
        psmt = conn.prepareStatement("INSERT INTO BBS VALUES(SEQ_BBS.NEXTVAL,?,?,?,DEFAULT,DEFAULT)");
        psmt.setString(1, dto.getUsername());
        psmt.setString(2, dto.getTitle());
        psmt.setString(3, dto.getContent());
        affected=psmt.executeUpdate();
        
        rs = psmt.getGeneratedKeys();
        if (rs.next()) {
            dto.setId(rs.getLong(1)); // ์‚ฝ์ž…๋œ ID๋ฅผ DTO์— ์„ค์ •
        }
        
      }
      catch(SQLException e) {e.printStackTrace();}
      return affected;
    }

    @Override
    public int update(BbsDTO dto) {
      int affected=0;
      try {
        psmt = conn.prepareStatement("UPDATE bbs SET title=?,content=? WHERE id=?");
        psmt.setLong(3, dto.getId());
        psmt.setString(1, dto.getTitle());
        psmt.setString(2, dto.getContent());
        affected=psmt.executeUpdate();
        
      }
      catch(SQLException e) {e.printStackTrace();}
      return affected;
    }

    // ์‚ญ์ œ์šฉ
    @Override
    public int delete(BbsDTO dto) {
      int affected=0;
      try {
        psmt = conn.prepareStatement("DELETE FROM bbs WHERE id=?");
        psmt.setLong(1, dto.getId());
        affected = psmt.executeUpdate();
      }
      catch(SQLException e) {e.printStackTrace();}
      return affected;
    }

    // ํšŒ์› ์—ฌ๋ถ€ ํŒ๋‹จ์šฉ
    public boolean isUser(String username, String password) {
      try {
        psmt = conn.prepareStatement("SELECT COUNT(*) FROM users WHERE username=? AND password=?");
        psmt.setString(1, username);
        psmt.setString(2, password);
        rs = psmt.executeQuery();
        rs.next();
        if(rs.getInt(1)==0) return false;
      
      }
      catch(SQLException e) {
        e.printStackTrace();
        return false;
      }
      return true;
    }

  }

BbsView.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œํŒ ์ƒ์„ธ ์กฐํšŒ JSP ๋กœ, ๊ฒŒ์‹œ๊ธ€์˜ ๋‚ด์šฉ๊ณผ ์ด์ „๊ธ€, ๋‹ค์Œ๊ธ€์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ธ์ฆ์„ ํ™•์ธํ•˜๊ณ , ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •, ์‚ญ์ œ, ๋ชฉ๋ก ์ด๋™ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.




  <%@page import="model.PagingUtil"%>
  <%@page import="java.util.Map"%>
  <%@page import="model.bbs.BbsDTO"%>
  <%@page import="java.util.List"%>
  <%@page import="model.bbs.BbsDAO"%>
  <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
  <!--  ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ํŒ๋‹จ:ํ•„ํ„ฐ ์‚ฌ์šฉ์‹œ ์•„๋ž˜ ์ฃผ์„์ฒ˜๋ฆฌ -->
  <%-- <jsp:include page="/common/IsUser.jsp" />--%>

  <%
    // 1.ํŒŒ๋ผ๋ฏธํ„ฐ(ํ‚ค๊ฐ’) ๋ฐ›๊ธฐ
    long id = Long.parseLong(request.getParameter("id"));
    // ํ˜„์žฌ ํŽ˜์ด์ง€๋ฒˆํ˜ธ ๋ฐ›๊ธฐ
    String nowPageParam = request.getParameter(PagingUtil.NOWPAGE);
      int nowPage = (nowPageParam != null && !nowPageParam.isEmpty()) ? Integer.parseInt(nowPageParam) : 1;
    // ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ -์‚ญ์ œ์šฉ
    String pageSizeParam = request.getParameter(PagingUtil.PAGE_SIZE);
      int pageSize = (pageSizeParam != null && !pageSizeParam.isEmpty()) ? Integer.parseInt(pageSizeParam) : 10;
    // ๊ฒ€์ƒ‰์‹œ
    String searchColumn = request.getParameter("searchColumn");
    String searchWord = request.getParameter("searchWord");
    String searchQuery="";
    if( searchColumn !=null && searchWord.length() !=0){		
      searchQuery=String.format("searchColumn=%s&searchWord=%s&", searchColumn,searchWord);
      
    }
    
    // 2.CRUD์ž‘์—…์šฉ BBSDao ์ƒ์„ฑ
    BbsDAO dao = new BbsDAO(application);
    // ์ด์ „ ํŽ˜์ด์ง€๋ช… ์–ป๊ธฐ:List.jsp์—์„œ ๋ทฐ๋กœ ์˜ฌ๋•Œ๋งŒ ์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€ ํ•˜๊ธฐ ์œ„ํ•จ
    String referer=request.getHeader("referer");
    String prevPage = referer.substring(referer.lastIndexOf("/")+1);
    // ๋ ˆ์ฝ”๋“œ ํ•˜๋‚˜ ๊ฐ€์ ธ์˜ค๊ธฐ
    BbsDTO item= dao.findById(String.valueOf(id),prevPage);	
    if(item==null){
      out.println("<script>");
      out.println("alert('์œ ํšจํ•˜์ง€ ์•Š๋Š” ๊ธ€ ๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค');");
      out.println("history.back();");
      out.println("</script>");
      dao.close();
      return;
      
    }
    // ๋‚ด์šฉ ์ค„๋ฐ”๊ฟˆ ์ฒ˜๋ฆฌ
    item.setContent(item.getContent().replace("\r\n", "<br/>"));
    // ์ด์ „๊ธ€, ๋‹ค์Œ๊ธ€ ์กฐํšŒ
    Map<String,BbsDTO> map= dao.prevNext(String.valueOf(id));	
    dao.close();
  %>

  <%
      // ์ฟ ํ‚ค์—์„œ ํ† ํฐ ๊ฐ€์ ธ์˜ค๊ธฐ
      Cookie[] cookies = request.getCookies();
      String token = null;
      if (cookies != null) {
          for (Cookie cookie : cookies) {
              if ("token".equals(cookie.getName())) {
                  token = cookie.getValue();
                  break;
              }
          }
      }

      // ์„ธ์…˜์—์„œ ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๊ฐ€์ ธ์˜ค๊ธฐ
      String username = (String) session.getAttribute("username");

      // ํ† ํฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
      boolean isValidToken = false;
      if (username != null && token != null) {
          model.user.UserDAO userDAO = new model.user.UserDAO();
          isValidToken = userDAO.validateToken(username, token);
          
          if (!isValidToken) {
              // ํ† ํฐ์ด ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๋ฉด ์„ธ์…˜ ๋ฌดํšจํ™” ๋ฐ ์ฟ ํ‚ค ์‚ญ์ œ
              session.invalidate();
              Cookie tokenCookie = new Cookie("token", null);
              tokenCookie.setMaxAge(0);
              response.addCookie(tokenCookie);
              username = null; // ๋น„๋กœ๊ทธ์ธ ์ƒํƒœ๋กœ ์„ค์ •
          }
      } else {
          // ์‚ฌ์šฉ์ž ์ด๋ฆ„์ด๋‚˜ ํ† ํฐ์ด ์—†์œผ๋ฉด ๋น„๋กœ๊ทธ์ธ ์ƒํƒœ๋กœ ์ฒ˜๋ฆฌ
          username = null;
      }
  %>

  <!DOCTYPE html>
  <html>
  <head>
  <%--@ include file="/template/Config.jsp" --%>
  <jsp:include page="/template/Config.jsp" />
  <title>BbsView.jsp</title>
  <style>
  th.bg-dark.text-white {
    text-align: center;
  }
  </style>
  <script>
      function isDelete(){
          var pageSize = "<%=pageSize %>";
          if(pageSize === null || pageSize === "") {
              pageSize = "10"; // ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •
          }
          if(confirm("์ •๋ง๋กœ ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?")){
              location.replace("/YoonSeongBinProj2/bbspage/BbsDelete.jsp?id=<%=item.getId()%>&<%=PagingUtil.NOWPAGE %>=<%=nowPage%>&<%=PagingUtil.PAGE_SIZE %>=" + pageSize);
          }
      }
  </script>
  </head>
  <body>
    <div class="container">
      <div class="container-fluid">
        <%--@ include file="/template/Header.jsp" --%>
        <jsp:include page="/template/Header.jsp" />

        <!-- ์ปจํ…์ธ  ์‹œ์ž‘ -->
        <div class="p-5 bg-success text-white">
          <h1 style="font-weight:bold">์ž‘์„ฑ๊ธ€ ์ƒ์„ธ ๋ณด๊ธฐ</h1>
        </div>
        <fieldset class="border rounded-3 p-3 text-center mt-2">
        <table class="table table-hover">
          <tbody>
            <tr >
              <th class="bg-dark w-25 text-white" >๋ฒˆํ˜ธ</th>
              <td><%=item.getId() %></td>
            </tr>
            <tr>
              <th class="bg-dark w-25 text-white">์ž‘์„ฑ์ž</th>
              <td><%=item.getUsername() %></td>
            </tr>
            <tr>
              <th class="bg-dark w-25 text-white">์ž‘์„ฑ์ผ</th>
              <td><%=item.getPostDate() %></td>
            </tr>
            <tr>
              <th class="bg-dark w-25 text-white">์กฐํšŒ์ˆ˜</th>
              <td><%=item.getHitCount() %></td>
            </tr>
            <tr>
              <th class="bg-dark w-25 text-white">์ œ๋ชฉ</th>
              <td><%=item.getTitle() %></td>
            </tr>
            <tr>
              <th class="bg-dark text-white" colspan="2">๋‚ด์šฉ</th>
            </tr>
            <tr>
              <td colspan="2"><%=item.getContent()%></td>
            </tr>

          </tbody>
        </table>
        <!-- ์ด์ „๊ธ€/๋‹ค์Œ๊ธ€ -->
        <div>
          <table class="table" >
            <tbody>
              
              <tr>
                <td class="text-white bg-dark w-25 text-center" style="font-weight:bold">๋‹ค์Œ๊ธ€</td>
                <td>
                <%=map.get("NEXT") == null ? "๋‹ค์Œ๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค" : String.format("<a href='/YoonSeongBinProj2/bbspage/BbsView.jsp?id=%s&%s=%s&%s=%s'>%s</a>",
                          map.get("NEXT").getId(), PagingUtil.NOWPAGE, nowPage, PagingUtil.PAGE_SIZE, pageSize, map.get("NEXT").getTitle()) %>
                </td>
              </tr>
              <tr>
                <td class="text-white bg-dark w-25 text-center" style="font-weight:bold">์ด์ „๊ธ€</td>
                <td>
                <%=map.get("PREV") == null ? "์ด์ „๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค" : String.format("<a href='/YoonSeongBinProj2/bbspage/BbsView.jsp?id=%s&%s=%s&%s=%s'>%s</a>",
                          map.get("PREV").getId(), PagingUtil.NOWPAGE, nowPage, PagingUtil.PAGE_SIZE, pageSize, map.get("PREV").getTitle()) %>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
        <!-- ์ˆ˜์ •/์‚ญ์ œ/๋ชฉ๋ก ์ปจํŠธ๋กค ๋ฒ„ํŠผ -->
        <div class="text-center">
          
          <% if (isValidToken && username != null && username.equals(item.getUsername())) { %>
          <a href="/YoonSeongBinProj2/bbspage/BbsEdit.jsp?id=<%=item.getId() %>&<%=PagingUtil.NOWPAGE+"="+nowPage %>" class="btn btn-success">์ˆ˜์ •</a> 
          <a href="javascript:isDelete()"	class="btn btn-success" >์‚ญ์ œ</a>				
          <a href="/YoonSeongBinProj2/bbspage/BbsList.jsp?<%=PagingUtil.NOWPAGE+"="+nowPage+"&"+searchQuery %>" class="btn btn-success">๋ชฉ๋ก</a>
          <% } else { %>
          <a href="/YoonSeongBinProj2/bbspage/BbsList.jsp?<%=PagingUtil.NOWPAGE+"="+nowPage+"&"+searchQuery %>" class="btn btn-success">๋ชฉ๋ก</a>
          <%}%>
        </div>
        </fieldset>
        <!-- ์ปจํ…์ธ  ๋ -->
        <%--@ include file="/template/Footer.jsp" --%>
        <jsp:include page="/template/Footer.jsp" />
      </div>
      <!-- container-fluid -->
    </div>
    <!--container  -->
  </body>
  </html>

BbsEdit.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” JSP ์ž…๋‹ˆ๋‹ค.

๊ฒŒ์‹œ๊ธ€ ID๋กœ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ณ , ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ํผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.




  <%@page import="model.PagingUtil"%>
  <%@page import="model.bbs.BbsDTO"%>
  <%@page import="java.util.List"%>
  <%@page import="model.bbs.BbsDAO"%>
  <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
  <!--  ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ํŒ๋‹จ:ํ•„ํ„ฐ ์‚ฌ์šฉ์‹œ ์•„๋ž˜ ์ฃผ์„์ฒ˜๋ฆฌ -->
  <%-- <jsp:include page="/common/IsUser.jsp" />--%>
  <%
      // ํŒŒ๋ผ๋ฏธํ„ฐ(id) ๊ฐ’์ด ์กด์žฌํ•˜๊ณ  ๋น„์–ด์žˆ์ง€ ์•Š์œผ๋ฉด long ํ˜•์œผ๋กœ ๋ณ€ํ™˜, ์•„๋‹ˆ๋ฉด ๊ธฐ๋ณธ๊ฐ’ 0L ์‚ฌ์šฉ
      String idParam = request.getParameter("id");
      long id = (idParam != null && !idParam.isEmpty()) ? Long.parseLong(idParam) : 0L;

      // ํ˜„์žฌ ํŽ˜์ด์ง€๋ฒˆํ˜ธ ๋ฐ›๊ธฐ
      String nowPage = request.getParameter(PagingUtil.NOWPAGE);
      
      // CRUD ์ž‘์—…์šฉ BbsDao ์ƒ์„ฑ
      BbsDAO dao = new BbsDAO(application);
      
      // ๋ ˆ์ฝ”๋“œ ํ•˜๋‚˜ ๊ฐ€์ ธ์˜ค๊ธฐ
      BbsDTO item = dao.findById(String.valueOf(id));

      // DAO ์‚ฌ์šฉ ํ›„ ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ
      dao.close();
  %>

  <!DOCTYPE html>
  <html>
  <head>
  <%--@ include file="/template/Config.jsp" --%>
  <jsp:include page="/template/Config.jsp" />
  <title>BbsEdit.jsp</title>

  </head>
  <body>
    <div class="container">
      <div class="container-fluid">
        <%--@ include file="/template/Header.jsp" --%>
        <jsp:include page="/template/Header.jsp" />

        <!-- ์ปจํ…์ธ  ์‹œ์ž‘ -->
        <div class="p-5 bg-success text-white mb-3">
          <h1 style="font-weight: bold;">ํšŒ์›์ œ ๊ฒŒ์‹œํŒ ์ˆ˜์ •</h1>
        </div>
        <fieldset class="border rounded-3 p-3 text-center">
          <legend class="float-none w-auto px-3" style="font-weight: bold;">์ˆ˜์ •ํ• 
            ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”</legend>
          <form action="/YoonSeongBinProj2/bbspage/BbsEditOk.jsp" method="post">

            <input type="hidden" name="id" value="<%=id%>" /> <input
              type="hidden" name="<%=PagingUtil.NOWPAGE%>" value="<%=nowPage%>" />

            <div class="row justify-content-center">
              <div class="col-md-8">
                <div class="row mb-3">

                  <div class="col-md-4 mb-2 mt-5 d-flex align-items-center justify-content-md-end">
                    <label for="title" class="form-label" style="font-weight: bold;">์ œ๋ชฉ</label>
                  </div>

                  <div class="col-md-6 mb-3 mt-5">
                    <input type="text" class="form-control" id="title" placeholder="Enter title" name="title" value="<%=item.getTitle()%>">
                  </div>
              </div>
                  <div class="row mb-3">
                    <div class="col-md-4 mb-2 mt-4 d-flex justify-content-md-end">
                      <label for="content" class="form-label" style="font-weight: bold;">๋‚ด์šฉ</label>
                    </div>

                    <div class="col-md-6 mb-3 mt-3">
                      <textarea placeholder="Enter content" class="form-control"
                        rows="18" id="content" name="content"><%=item.getContent()%></textarea>
                    </div>
                  </div>

                  <div class="row mb-3">
                    <div class="col-md-12">
                      <button type="submit" class="btn btn-dark ml-auto" style="padding: 10px 30px;">์ˆ˜์ •</button>
                    </div>
                  </div>
                </div>
              
            </div>
          </form>
        </fieldset>

        <!-- ์ปจํ…์ธ  ๋ -->
        <%--@ include file="/template/Footer.jsp" --%>
        <jsp:include page="/template/Footer.jsp" />
      </div>
      <!-- container-fluid -->
    </div>
    <!--container  -->
  </body>
  </html>

BbsList.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œํŒ์˜ ๊ธ€ ๋ชฉ๋ก์„ ํ‘œ์‹œํ•˜๋Š” JSP ์ž…๋‹ˆ๋‹ค.

๊ฒ€์ƒ‰ ๋ฐ ํŽ˜์ด์ง• ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์„ ํ…Œ์ด๋ธ” ํ˜•์‹์œผ๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•œ ๊ฒฝ์šฐ ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก ๋ฒ„ํŠผ์„ ํ‘œ์‹œํ•˜๊ณ , ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์ œ๋ชฉ, ๋‚ด์šฉ, ์ž‘์„ฑ์ž ๊ธฐ์ค€์œผ๋กœ ๊ฒŒ์‹œ๊ธ€์„ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.




  <%@page import="model.PagingUtil"%>
  <%@page import="java.util.HashMap"%>
  <%@page import="java.util.Map"%>
  <%@page import="model.bbs.BbsDTO"%>
  <%@page import="java.util.List"%>
  <%@page import="model.bbs.BbsDAO"%>
  <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
  <!--  ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ํŒ๋‹จ:ํ•„ํ„ฐ ์‚ฌ์šฉ์‹œ ์•„๋ž˜ ์ฃผ์„์ฒ˜๋ฆฌ -->
  <%-- <jsp:include page="/common/IsUser.jsp" />--%>
  <%
  // ๊ฒ€์ƒ‰๊ณผ ๊ด€๋ จ๋œ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ›๊ธฐ
  String searchColumn = request.getParameter("searchColumn"); // ๊ฒ€์ƒ‰ ์ปฌ๋Ÿผ
  String searchWord = request.getParameter("searchWord"); // ๊ฒ€์ƒ‰์–ด
  Map<String, String> map = new HashMap<>(); // ๊ฒ€์ƒ‰ ์กฐ๊ฑด ๋‹ด์„ ๋งต ์ƒ์„ฑ
  String linkUrl = request.getContextPath() + "/YoonSeongBinProj2/bbspage/BbsList.jsp?"; // ๋งํฌ URL ์ดˆ๊ธฐํ™”
  String searchQuery = ""; // ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ์ดˆ๊ธฐํ™”
  if (searchColumn != null && searchWord != null && !searchWord.isEmpty()) {
    map.put("searchColumn", searchColumn); // ๊ฒ€์ƒ‰ ์ปฌ๋Ÿผ ์ถ”๊ฐ€
    map.put("searchWord", searchWord); // ๊ฒ€์ƒ‰์–ด ์ถ”๊ฐ€
    searchQuery = String.format("searchColumn=%s&searchWord=%s&", searchColumn, searchWord); // ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ํ˜•์‹ ์ง€์ •
    linkUrl += searchQuery; // ๋งํฌ URL์— ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ์ถ”๊ฐ€
  }
  // ์ „์ฒด ๊ธ€ ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ	
  BbsDAO dao = new BbsDAO(application);


   map.put(PagingUtil.PAGE_SIZE, this.getInitParameter("PAGE-SIZE"));  // ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ์„ค์ •
    map.put(PagingUtil.BLOCK_PAGE, this.getInitParameter("BLOCK-PAGE"));  // ํŽ˜์ด์ง€ ๋ธ”๋ก ์‚ฌ์ด์ฆˆ ์„ค์ •
    PagingUtil.setMapForPaging(map, dao, request);  // ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ์„ค์ •
    int totalRecordCount = Integer.parseInt(map.get(PagingUtil.TOTAL_RECORD_COUNT));  // ์ „์ฒด ๊ธ€ ๊ฐœ์ˆ˜
    int pageSize = Integer.parseInt(map.get(PagingUtil.PAGE_SIZE));  // ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ
    int blockPage = Integer.parseInt(map.get(PagingUtil.BLOCK_PAGE));  // ๋ธ”๋ก ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ
    int nowPage = Integer.parseInt(map.get(PagingUtil.NOWPAGE));  // ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ
    // ํŽ˜์ด์ง•์„ ์œ„ํ•œ ๋กœ์ง ๋
    List<BbsDTO> items = dao.findAll(map);  // ์ „์ฒด ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ

    dao.close();  // DB ์—ฐ๊ฒฐ ์ข…๋ฃŒ
  %>


  <!DOCTYPE html>
  <html>
  <head>
  <%--@ include file="/template/Config.jsp" --%>
  <jsp:include page="/template/Config.jsp" />
  <title>BbsList.jsp</title>

  </head>
  <body>
    <div class="container">
      <div class="container-fluid">
        <%--@ include file="/template/Header.jsp" --%>
        <jsp:include page="/template/Header.jsp" />

        <!-- ์ปจํ…์ธ  ์‹œ์ž‘ -->
        <div class="p-5 bg-success text-white mb-3">
          <h1 style="font-weight: bold;">๊ฒŒ์‹œํŒ ๋ชฉ๋ก</h1>
        </div>
        <div class="my-2 text-end">
        <% String username = (String) session.getAttribute("username");
                    String token = (String) session.getAttribute("token");
                    if (username != null && token != null) { %>
          <a href="BbsWrite.jsp" class="btn btn-danger">๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก</a>
          <% } else {} %>
            
        </div>
        <table class="table table-hover text-center">
          <thead class="table-dark">
            <tr>
              <th class="col-1">๋ฒˆํ˜ธ</th>
              <th class="col-auto">์ œ๋ชฉ</th>
              <th class="col-2">์ž‘์„ฑ์ž</th>
              <th class="col-1">์กฐํšŒ์ˆ˜</th>
              <th class="col-2">์ž‘์„ฑ์ผ</th>
            </tr>
          </thead>
          <tbody>
            <%
            // ๊ฒŒ์‹œ๊ธ€์ด ์—†์œผ๋ฉด "๋“ฑ๋ก๋œ ๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค" ํ‘œ์‹œ
            if (items.isEmpty()) {
            %>
            <tr>
              <td colspan="5">๋“ฑ๋ก๋œ ๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.</td> 
            </tr>
            <%
            // ๊ฒŒ์‹œ๊ธ€์ด ์žˆ์œผ๋ฉด ๋ชฉ๋ก ์ถœ๋ ฅ
            } else {
            int loop = 0;
            for (BbsDTO item : items) {
            %>
            <tr>
              <td><%=totalRecordCount - (((nowPage - 1) * pageSize) + loop)%></td>
              <td class="text-start"><a
                href="BbsView.jsp?id=<%=item.getId() + "&" + PagingUtil.NOWPAGE + "=" + nowPage + "&" + searchQuery + PagingUtil.PAGE_SIZE + "="
      + pageSize%>"><%=item.getTitle()%></a></td>
              <td><%=item.getUsername()%></td>
              <td><%=item.getHitCount()%></td>
              <td><%=item.getPostDate()%></td>
            </tr>
            <%
            loop++;
            }
            }
            %>
          </tbody>
        </table>
        <!-- ํŽ˜์ด์ง• ์ถœ๋ ฅ -->
        <%=PagingUtil.pagingBootStrapStyle(totalRecordCount, pageSize, blockPage, nowPage, linkUrl)%>
        <!-- ๊ฒ€์ƒ‰ UI -->

        <form method="post" class="row justify-content-center"> // ๊ฒ€์ƒ‰ ํผ

          <div class="col-2">
            <select class="form-control" name="searchColumn">
              <option value="title">์ œ๋ชฉ</option>
              <option value="content">๋‚ด์šฉ</option>
              <option value="username"> ์ž‘์„ฑ์ž</option>
            </select>
          </div>
          <div class="col-5">
            <input type="text" class="form-control mx-2"
              placeholder="๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”" name="searchWord" />
          </div>
          <div class="col-auto">
            <button type="submit" class="btn btn-primary">๊ฒ€์ƒ‰</button>
          </div>

        </form>
        <!-- ์ปจํ…์ธ  ๋ -->
        <jsp:include page="/template/Footer.jsp" />
      </div>
      <!-- container-fluid -->
    </div>
    <!--container  -->
  </body>
  </html>

BbsDelete.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œ๊ธ€์„ ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ JSP ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์‚ญ์ œํ•˜๋ ค๋Š” ๊ฒŒ์‹œ๊ธ€์˜ ID๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„ ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์„ ์‚ญ์ œํ•œ ํ›„, ์‚ญ์ œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋ฉด ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•ฉ๋‹ˆ๋‹ค.

์‚ญ์ œ์— ์‹คํŒจํ•œ ๊ฒฝ์šฐ, ์•Œ๋ฆผ ์ฐฝ์„ ๋„์šฐ๊ณ  ์ด์ „ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.

์‚ญ์ œ ํ›„ ์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜๋ฅผ ์žฌ๊ณ„์‚ฐํ•˜๊ณ , ํ˜„์žฌ ํŽ˜์ด์ง€๊ฐ€ ์‚ญ์ œ ํ›„ ํŽ˜์ด์ง€ ์ˆ˜๋ณด๋‹ค ๋งŽ์œผ๋ฉด ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.




  <%@page import="java.util.HashMap"%>
  <%@page import="java.util.Map"%>
  <%@page import="model.PagingUtil"%>
  <%@page import="model.bbs.BbsDTO"%>
  <%@page import="model.bbs.BbsDAO"%>
  <%@ page language="java" contentType="text/html; charset=UTF-8"
      pageEncoding="UTF-8"%>
  <!-- Delete.jsp -->
  <!--  ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ํŒ๋‹จ:ํ•„ํ„ฐ ์‚ฌ์šฉ์‹œ ์•„๋ž˜ ์ฃผ์„์ฒ˜๋ฆฌ -->
  <%-- <jsp:include page="/common/IsUser.jsp" />--%>
  <%
    
    // 1.ํŒŒ๋ผ๋ฏธํ„ฐ(ํ‚ค๊ฐ’) ๋ฐ›๊ธฐ	
    long id = Long.parseLong(request.getParameter("id"));
    //ํ˜„์žฌ ํŽ˜์ด์ง€๋ฒˆํ˜ธ ๋ฐ›๊ธฐ
    int nowPage = request.getParameter(PagingUtil.NOWPAGE) == null ? 1 : Integer.parseInt(request.getParameter(PagingUtil.NOWPAGE));
    //ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ -์‚ญ์ œ์šฉ
    int pageSize = request.getParameter(PagingUtil.PAGE_SIZE) == null ? 10 : Integer.parseInt(request.getParameter(PagingUtil.PAGE_SIZE));
    
    
    // 2.CRUD์ž‘์—…์šฉ BbsDao์ƒ์„ฑ
    BbsDAO dao = new BbsDAO(application);	
    BbsDTO dto = new BbsDTO();
    dto.setId(id);
    int affected=dao.delete(dto);
    // ์‚ญ์ œ ํ›„์— ์ด ํŽ˜์ด์ง€ ์ˆ˜ ๊ตฌํ•จ
    int totalRecordCount = dao.getTotalRecordCount(null); // ๊ฒ€์ƒ‰์‹œ๋„ ์ ์šฉ ์‹œ๋Š” ๋ฐ˜๋“œ์‹œ ๋งต ์ „๋‹ฌ
    
    int totalPage=(int)Math.ceil((double)totalRecordCount/pageSize);
    dao.close();
    if(totalPage < nowPage) nowPage=totalPage;
    
    
    if(affected==1){
      response.sendRedirect("/YoonSeongBinProj2/bbspage/BbsList.jsp?"+PagingUtil.NOWPAGE+"="+nowPage);
    }
    else{
      out.println("<script>");
      out.println("alert('์‚ญ์ œ ์‹คํŒจํ–ˆ์–ด์š”');");
      out.println("history.back();");
      out.println("</script>");
    }

  %>

BbsWrite.jsp

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•˜๋Š” JSP ๋กœ, ์‚ฌ์šฉ์ž์—๊ฒŒ ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ž…๋ ฅ๋ฐ›๋Š” ํผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํผ์— ์ž…๋ ฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ 'WriteController'๋กœ POST ๋ฐฉ์‹์œผ๋กœ ์ „์†กํ•˜์—ฌ ๊ฒŒ์‹œ๊ธ€์„ ๋“ฑ๋กํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํผ ๋‚ด์—๋Š” ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ ์ž…๋ ฅ ํ•„๋“œ๊ฐ€ ์žˆ์œผ๋ฉฐ, ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ์„ ์™„๋ฃŒํ•œ ํ›„ '๋“ฑ๋ก' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์„œ๋ฒ„๋กœ ์ „๋‹ฌ๋˜์–ด ๊ฒŒ์‹œ๊ธ€์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.




  <%@ 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>
    <jsp:include page="/template/Config.jsp" />
    <title>BbsWrite.jsp</title>
  </head>
  <body>
      <div class="container">
          <div class="container-fluid">
              <jsp:include page="/template/Header.jsp" />
              <!-- ์ปจํ…์ธ  ์‹œ์ž‘ -->
              <div class="p-5 bg-success text-white mb-3">
                  <h1 style="font-weight: bold;">๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก</h1>
              </div>
              <fieldset class="border rounded-3 p-3 text-center">
                  <legend class="float-none w-auto px-3" style="font-weight: bold;">๋“ฑ๋กํ•  ์ œ๋ชฉ๊ณผ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”</legend>  // ํผ ์ œ๋ชฉ
                  <form action="${pageContext.request.contextPath}/WriteController" method="post">  // ํผ ์ œ์ถœ ์•ก์…˜
                    <div class="row justify-content-center">
                        <div class="col-md-8">
                            <div class="row mb-3">  // ์ œ๋ชฉ ์ž…๋ ฅ ํผ
                                <div class="col-md-4 mb-2 mt-5 d-flex align-items-center justify-content-md-end">
                                    <label for="title" class="form-label" style="font-weight: bold;">์ œ๋ชฉ</label>
                                </div>
                                <div class="col-md-6 mb-3 mt-5">  // ์ œ๋ชฉ ์ž…๋ ฅ ํ•„๋“œ
                                    <input type="text" class="form-control" id="title" placeholder="์ œ๋ชฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”" name="title">
                                </div>
                            </div>
                            <div class="row mb-3">  // ๊ธ€ ๋‚ด์šฉ ์ž…๋ ฅ ํผ
                                <div class="col-md-4 mb-2 mt-4 d-flex justify-content-md-end">
                                    <label for="content" class="form-label" style="font-weight: bold;">๊ธ€ ๋‚ด์šฉ</label>
                                </div>
                                <div class="col-md-6 mb-3 mt-3">  // ๋‚ด์šฉ ์ž…๋ ฅ ํ•„๋“œ
                                    <textarea class="form-control" rows="18" id="content" name="content" placeholder="๊ธ€์„ ์ž…๋ ฅํ•˜์„ธ์š”"></textarea>
                                </div>
                            </div>
                            <div class="row mb-3">  // ๋“ฑ๋ก ๋ฒ„ํŠผ
                                <div class="col-md-12">
                                    <button type="submit" class="btn btn-dark ml-auto" style="padding: 10px 30px;">๋“ฑ๋ก</button>
                                </div>
                            </div>
                        </div>
                    </div>
                  </form>
              </fieldset>
              <!-- ์ปจํ…์ธ  ๋ -->
              <jsp:include page="/template/Footer.jsp" />
          </div>
          <!-- container-fluid -->
      </div>
      <!--container  -->
  </body>
  </html>



4. ์‹คํ–‰ ๊ฒฐ๊ณผ

์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.