JAVA/JSP 프로그래밍

JSTL을 활용한 게시판 기능 만들기(댓글 - 수정)

미로910 2024. 7. 17. 15:32

https://maze910.tistory.com/138

 

JSP 게시판 만들기(로그인, 회원가입, 게시글 리스트)

기본 구성회원가입: 사용자가 회원가입을 할 수 있는 기능회원탈퇴: 사용자가 회원탈퇴를 할 수 있는 기능로그인 및 로그아웃: 사용자가 로그인하고 로그아웃할 수 있는 기능회원 관리 기능게

maze910.tistory.com

이어서 댓글 - 수정까지 만들어 보기

BoardController
package com.tenco.controller;

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

import java.io.IOException;
import java.sql.Connection;
import java.util.List;

import com.tenco.model.Board;
import com.tenco.model.Comment;
import com.tenco.model.User;
import com.tenco.repository.interfaces.BoardRepository;
import com.tenco.repository.interfaces.BoardRepositoyImpl;
import com.tenco.repository.interfaces.CommentRepository;
import com.tenco.repository.interfaces.CommentRepositoryImpl;
import com.tenco.util.DBUtil;

@WebServlet("/board/*")
public class BoardController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private BoardRepository boardRepository;
	private CommentRepository commentRepository;

	@Override
	public void init() throws ServletException {
		boardRepository = new BoardRepositoyImpl();
		commentRepository = new CommentRepositoryImpl();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String action = request.getPathInfo();
		HttpSession session = request.getSession(false);
		if (session == null || session.getAttribute("principal") == null) {
			response.sendRedirect(request.getContextPath() + "/user/signin");
			return;
		}
		System.out.println("action : " + action);
		switch (action) {
		case "/delete":
			handleDeleteBoard(request, response, session);
			break;
		case "/update":
			showEditBoardForm(request, response, session);
			break;
		case "/create":
			showCreateBoardForm(request, response, session);
			break;

		case "/list":

			handleListBoards(request, response, session);
			break;
		case "/view":

			showViewBoard(request, response, session);
			break;
		case "/deleteComment":

			handleDeleteComment(request, response, session);
			break;

		default:
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
			break;
		}

	}

	// 수정 폼 화면 이동 (인증 검사 반드시 처리)
	private void showEditBoardForm(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
		// TODO Auto-generated method stub

	}

	// 게시글 삭제
	private void handleDeleteBoard(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
		// TODO Auto-generated method stub

	}

	// 댓글 삭제 기능
	private void handleDeleteComment(HttpServletRequest request, HttpServletResponse response, HttpSession session) {

	}

	// 상세 보기 화면 이동
	private void showViewBoard(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
		try {
			int boardId = Integer.parseInt(request.getParameter("id"));
			Board board = boardRepository.getBoardById(boardId);
			
			if (board == null) {
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
		
			// 현재 로그인한 사용자의 ID
			User user = (User) session.getAttribute("principal");
			if (user != null) {
				request.setAttribute("userID", user.getId());
			}

			List<Comment> commentList = commentRepository.getCommentsByBoardId(boardId);
			
			request.setAttribute("board", board);
			request.setAttribute("commentList", commentList);
			request.getRequestDispatcher("/WEB-INF/views/board/view.jsp").forward(request, response);
			
			//

		} catch (Exception e) {
			// TODO: handle exception
		}

	}

	// 게시글 생성 화면 이동
	private void showCreateBoardForm(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/views/board/create.jsp").forward(request, response);

	}

	// 페이징 처리 하기
	private void handleListBoards(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws ServletException, IOException {

		// 게시글 목록 조회 기능
		int page = 1; // 기본 페이지 번호
		int pageSize = 3; // 한 페이지 당 보여질 게시글에 수

		try {
			String pageStr = request.getParameter("page");
			if (pageStr != null) {
				page = Integer.parseInt(pageStr);
			}
		} catch (Exception e) {
			// 유효하지 않은 번호를 마음대로 보낼 경우
			page = 1;
		}

		// pageSize --> 3이다
		// page 1, page 2, page 3 요청 동적으로 시작값을 계산하는 산수 공식 넣기
		int offset = (page - 1) * 3; // 시작 위치 계산( offset 값 계산)

		// pageSize <-- 한 페이지당 보여줄 게시글 수 (limit 로 바라 볼 수 있다)
		List<Board> boardList = boardRepository.getAllBoards(pageSize, offset);

		// 페이징 처리 1단계 (현재 페이지 번호, pageSize, offset)
		////////////////////////////////////////////////////////

		// 전체 게시글 수 조회
		int totalBoards = boardRepository.getTotalBoardCount();

		// 총 페이지 수 계산 -> [1][2][3][...]
		int totalPages = (int) Math.ceil((double) totalBoards / pageSize);

		request.setAttribute("boardList", boardList);
		request.setAttribute("totalPages", totalPages);
		System.out.println("총 페이지 블록 수 : " + totalPages);
		request.setAttribute("currentPage", page);

		// 현재 로그인한 사용자 ID 설정
		if (session != null) {
			User user = (User) session.getAttribute("principal");
			if (user != null) {
				request.setAttribute("userId", user.getId());
			}
		}

		request.getRequestDispatcher("/WEB-INF/views/board/list.jsp").forward(request, response);

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String action = request.getPathInfo();
		HttpSession session = request.getSession(false);
		if (session == null || session.getAttribute("principal") == null) {
			response.sendRedirect(request.getContextPath() + "/user/signin");
			return;
		}

		switch (action) {
		case "/create":
			handleCreateBoard(request, response, session);
			break;

		case "/edit":

			break;

		case "/addComment":
			handleAddComment(request, response, session);
			break;

		default:
			response.sendError(HttpServletResponse.SC_NOT_FOUND);
			break;
		}
	}

	// 댓글 달기
	private void handleAddComment(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
		int boardid = Integer.parseInt(request.getParameter("id"));
		
		User user = (User) session.getAttribute("principal");
		
		String content = request.getParameter("content");
		
		Comment comment = Comment.builder().boardId(boardid)
										   .userId(user.getId())
										   .content(content)
										   .build();
		commentRepository.addComment(comment);
		
		response.sendRedirect(request.getContextPath() + "/board/view?id=" + boardid);
		
		
		
	}

	// 게시글 생성 처리
	private void handleCreateBoard(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws IOException {

		// 유효성 검사 생략
		String title = request.getParameter("title");
		String content = request.getParameter("content");
		User user = (User) session.getAttribute("principal");

		Board board = Board.builder().userId(user.getId()).title(title).content(content).build();
		boardRepository.addBoard(board);
		response.sendRedirect(request.getContextPath() + "/board/list?page=1");
	}

}

 

Comment.java 생성
package com.tenco.model;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
public class Comment {

	private int id;
	private int boardId;
	private int userId;
	private String content;
	private Timestamp createdAt;
	private String username;
}

 

CommentRepository - interface 생성
package com.tenco.repository.interfaces;

import java.util.List;

import com.tenco.model.Comment;

public interface CommentRepository {

	void addComment(Comment comment);
	void deleteComment(int id);
	Comment getCommentById(int id);
	List<Comment> getCommentsByBoardId(int boardId);
	
	
}

 

CommentRepositoryImpl 생성
package com.tenco.repository.interfaces;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import com.tenco.model.Comment;
import com.tenco.util.DBUtil;

public class CommentRepositoryImpl implements CommentRepository {

	private static final String INSERT_COMMNET_SQL = "  INSERT INTO comments (board_id, user_id, content) VALUES (?, ? , ?) ";
	private static final String DELETE_COMMNET_SQL = "  DELETE FROM comments WHERE id = ? ";
	private static final String SELECT_COMMNET_BY_ID = " SELECT * FROM comments WHERE id = ? ";
	private static final String SELECT_COMMNET_BY_BOARD_ID = " SELECT c.*, u.username "
															+ " FROM comments as c "
															+ " join users as u on c.user_id = u.id "
															+ " WHERE board_id = ? "
															+ " ORDER BY created_at DESC ";

	@Override
	public void addComment(Comment comment) {
		try (Connection conn = DBUtil.getConnection()) {
			conn.setAutoCommit(false);

			try (PreparedStatement pstmt = conn.prepareStatement(INSERT_COMMNET_SQL)) {
				pstmt.setInt(1, comment.getBoardId());
				pstmt.setInt(2, comment.getUserId());
				pstmt.setString(3, comment.getContent());
				pstmt.executeUpdate();
				conn.commit();
			} catch (Exception e) {
				conn.rollback();
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public void deleteComment(int id) {
		try (Connection conn = DBUtil.getConnection()) {
			conn.setAutoCommit(false);

			try (PreparedStatement pstmt = conn.prepareStatement(DELETE_COMMNET_SQL)) {
				pstmt.setInt(1, id);

				pstmt.executeUpdate();
				conn.commit();
			} catch (Exception e) {
				conn.rollback();
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public Comment getCommentById(int id) {
		Comment comment = null;
		try (Connection conn = DBUtil.getConnection();
				PreparedStatement pstmt = conn.prepareStatement(SELECT_COMMNET_BY_ID)) {
			pstmt.setInt(1, id);

			try (ResultSet rs = pstmt.executeQuery()) {
				if (rs.next()) {
					comment = new Comment(rs.getInt("id"), rs.getInt("board_id"), rs.getInt("user_id"),
							rs.getString("content"), rs.getTimestamp("created_at"), rs.getString("username"));
				}

			} catch (Exception e) {
				e.printStackTrace();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return comment;
	}

	@Override
	public List<Comment> getCommentsByBoardId(int boardId) {
		List<Comment> commentList = new ArrayList<>();

		try (Connection conn = DBUtil.getConnection();
				PreparedStatement pstmt = conn.prepareStatement(SELECT_COMMNET_BY_BOARD_ID)) {
			pstmt.setInt(1, boardId);

			try (ResultSet rs = pstmt.executeQuery()) {
				while (rs.next()) {
					Comment comment = new Comment(rs.getInt("id"), rs.getInt("board_id"), rs.getInt("user_id"),
							rs.getString("content"), rs.getTimestamp("created_at"), rs.getString("username"));
					commentList.add(comment);
				}

			} catch (Exception e) {
				e.printStackTrace();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return commentList;
	}

}

 

list.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 uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
   
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시글 목록</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/css/common.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/css/list.css">
</head>
<body>
    <h2>게시글 목록</h2>
    <div class="action">
        <a class="btn btn-create" href="${pageContext.request.contextPath}/board/create" >새글 작성하기</a>
        <a class="btn btn-back" href="${pageContext.request.contextPath}/index.jsp" >홈 화면</a>
    </div>
    
    <c:forEach var="board"  items="${boardList}">
        <div class="board-item">
            <h3><a href="${pageContext.request.contextPath}/board/view?id=${board.id}">${board.title}</a></h3>
            <p>${board.content}</p>
            <p> <fmt:formatDate value="${board.createdAt}" pattern="yyyy-MM-dd HH:mm" /></p>
            <!-- 게시글에 작성자가 세션 유저와 동일하다면 수정, 삭제 버튼을 보여주자  -->
            <c:if test="${board.userId==userId }">
                <a class="btn btn-edit" href="#">수정</a>
                <a class="btn btn-delete" href="#">삭제</a>
            </c:if>
        </div>
    </c:forEach>
    
    <br>
    <div class="pagination">
        <!-- index for  -->
        <c:forEach begin="1" end="${totalPages}"  var="i" >
            <c:choose>
                <c:when test="${ i == currentPage }">
                    <span class="current-page" >${i}</span>
                </c:when>
                <c:otherwise>
                    <span><a href="${pageContext.request.contextPath}/board/list?page=${i}">${i}</a></span>    
                </c:otherwise>
            </c:choose>
        </c:forEach>
    </div>
    
</body>
</html>

 

view.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 uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
   
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>게시글 목록</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/css/common.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/css/list.css">
</head>
<body>
    <h2>게시글 목록</h2>
    <div class="action">
        <a class="btn btn-create" href="${pageContext.request.contextPath}/board/create" >새글 작성하기</a>
        <a class="btn btn-back" href="${pageContext.request.contextPath}/index.jsp" >홈 화면</a>
    </div>
    
    <c:forEach var="board"  items="${boardList}">
        <div class="board-item">
            <h3><a href="${pageContext.request.contextPath}/board/view?id=${board.id}">${board.title}</a></h3>
            <p>${board.content}</p>
            <p> <fmt:formatDate value="${board.createdAt}" pattern="yyyy-MM-dd HH:mm" /></p>
            <!-- 게시글에 작성자가 세션 유저와 동일하다면 수정, 삭제 버튼을 보여주자  -->
            <c:if test="${board.userId==userId }">
                <a class="btn btn-edit" href="#">수정</a>
                <a class="btn btn-delete" href="#">삭제</a>
            </c:if>
        </div>
    </c:forEach>
    
    <br>
    <div class="pagination">
        <!-- index for  -->
        <c:forEach begin="1" end="${totalPages}"  var="i" >
            <c:choose>
                <c:when test="${ i == currentPage }">
                    <span class="current-page" >${i}</span>
                </c:when>
                <c:otherwise>
                    <span><a href="${pageContext.request.contextPath}/board/list?page=${i}">${i}</a></span>    
                </c:otherwise>
            </c:choose>
        </c:forEach>
    </div>
    
</body>
</html>