본문 바로가기
JSP

[게시판 Ver.2] 게시글과 댓글의 화면 출력

by amoomar 2022. 3. 14.
반응형

 

이 포스팅의 목차는 다음과 같다.


1.  에러문구 출력_EL

2. 게시글과 댓글의 화면 출력

   1) model
   2) view
   3) controller

 

 


 

 

1.  에러문구 출력_EL

view부분에서 EL식을 활용해 자바와 관련된 코드(표현식)을 삭제할 수 있다. 이때 에러 문구의 출력과 관련하여 pageContext의 객체에 접근하게 되는데, 오류 문구의 출력에서 자주 사용되는 내용을 3개로 구분해 아래에 정리하였다.

 

EL 설명
${pageContext.errorData.throwable} 예외의 유형을 확인할 수 있다.
${pageContext.errorData.requestURI} 요청 실패가 발생한 url을 확인할 수 있다.
${pageContext.errorData.statusCode} 에러의 상태코드를 확인할 수 있다.

 

 


 

 

2. 게시글과 댓글의 화면 출력

해당 포스팅을 이해하고, 활용하면 게시글&댓글의 출력과 댓글&대댓글 등 여러 방면으로 응용이 가능하다.

 

1) model

 

① 타입 정의

만일 한 페이지에 출력되어야할 데이터가 각기 다른 테이블이라면 두 테이블을 한 번에 리스트로 반환할 수 있는 자료형을 class파일로 생성해주어야한다.

 

아래의 코드로 한 페이지에 뿌려질 데이터의 타입을 정의해보았다. (게시글1개와 그에 대한 여러개의 댓글을 반환)

 

 

BoardSet.java

package model.vo;

import java.util.ArrayList;

//두 테이블을 연관지어 들고다닐 자료형 가방
public class BoardSet {
	private BoardVO boardVO; //게시글자료형
	private ArrayList<ReplyVO> replyList=new ArrayList<ReplyVO>(); //댓글리스트
	
	public BoardVO getBoardVO() {
		return boardVO;
	}
	public ArrayList<ReplyVO> getReplyList() {
		return replyList;
	}
	public void setBoardVO(BoardVO boardVO) {
		this.boardVO = boardVO;
	}
	public void setReplyList(ArrayList<ReplyVO> replyList) {
		this.replyList = replyList;
	}
	
	@Override
	public String toString() {
		return "BoardSet [boardVO=" + boardVO + ", replyList=" + replyList + "]";
	}
}

 

 


 

 

② selectAll( )

주석을 통해 내용을 이해할 수 있다. 추가로 update관련 sql문을 활용하여 cnt를 누적하는 방식으로 "좋아요"기능도 구현할 수 있다.

package model.dao;

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

import model.common.JDBCUtill;
import model.vo.BoardSet;
import model.vo.BoardVO;
import model.vo.ReplyVO;

public class BoardDAO { // BoardSet을 다루는 DAO클래스
   Connection conn;
   PreparedStatement pstmt;
   
   // 1. 둘 다 출력해내야하기 때문에 각각의 table마다 selectAll을 할 수 있는 sql문이 필요하다.
   // 2. 최신순으로 조회할 목적으로 내림차순 정렬하며,
   //    페이징처리(한 화면에서 볼 수 있는 데이터 수를 지정)를 목적으로 limit 0부터 ?까지로 지정한다.
   static final String selectAll_board="select * from board order by bid desc limit 0,?";
   //3. 마찬가지로 내림차순 정렬하며, 어떤 게시글에 대한 selectAll인지 where절을 활용하여 구분한다.
   static final String selectAll_reply="select * from reply where bid=? order by rid desc";
   
   // 전체 글+댓글 출력 ☆
   
   // 4. controller에서 전달하던, view에서 전달하던
   //   어쨌는 model은 모르는 int이기 때문에 인자로 받을 수 있도록 한다, 
   public ArrayList<BoardSet> selectAll(int cnt){ 
      ArrayList<BoardSet> datas=new ArrayList<BoardSet>();
      conn=JDBCUtill.connect();
      try {
         pstmt=conn.prepareStatement(selectAll_board);
         pstmt.setInt(1, cnt);
         ResultSet rs=pstmt.executeQuery();
         while(rs.next()) {
         
         // 6. BoardSet객체에 각각 필요한 값을 담기 위해 초기화 진행
            BoardSet bs=new BoardSet();
            
         //  7. boardSet에 필요한 값중 하나 BoardVO의 내용물들!
         //		초기화하고, bs에 set해준다.
            BoardVO boardVO=new BoardVO();
            boardVO.setBdate(rs.getString("bdate"));
            boardVO.setBid(rs.getInt("bid"));
            boardVO.setContent(rs.getString("content"));
            boardVO.setFavcnt(rs.getInt("favcnt"));
            boardVO.setMid(rs.getString("mid"));
            boardVO.setRpcnt(rs.getInt("rpcnt"));
            bs.setBoardVO(boardVO);

	     //  8. boardSet에 필요한 값중 하나 Reply리스트!
         //		리스트 먼저 초기화, 쿼리문 변경하여 진행하고
         //		리스트에 넣어야할 ReplyVO객체를 또 초기화! 최종 내용을 bs.set해주기
            ArrayList<ReplyVO> replyList=new ArrayList<ReplyVO>();
            pstmt=conn.prepareStatement(selectAll_reply);
            pstmt.setInt(1, rs.getInt("bid"));
            ResultSet rs2=pstmt.executeQuery(); //다른 ResultSet
            while(rs2.next()) {
               ReplyVO replyVO=new ReplyVO();
               replyVO.setBid(rs2.getInt("bid"));
               replyVO.setMid(rs2.getString("mid"));
               replyVO.setMsg(rs2.getString("msg"));
               replyVO.setRdate(rs2.getString("rdate"));
               replyVO.setRid(rs2.getInt("rid"));
               replyList.add(replyVO);
            }
            rs2.close();
            bs.setReplyList(replyList);
            
            //5. 최종적으로 datas에 넣어야하는 것은 BoardSet의 객체이다.
            datas.add(bs); 
         }
         rs.close();
      } catch (SQLException e) {
         e.printStackTrace();
      }
      JDBCUtill.disconnect(pstmt, conn);
      return datas;
   } 	
}

흐름을 쫓아가며 역순으로 작업하면 이해하기 수월하다.

 

* SQL문에서 사용된 limit은 mysql에서 사용이 가능하며 oracle에서는 rownum으로 대체하여 사용할 수 있다. *

 

 


 

2) view

<c:forEach var="v" items="datas">로 작업하게 되면 해당 datas 내부에 두개의 값이 존재하기 때문에 한번 더 접근이 필요하다. 즉 각각의 값을 접근할때마다 사용되는 EL을 작성하는 것이 번거롭기 때문에 <c:set>을 적절히 활용하여 아래와 같이 관리할 수 있다.

<%@ 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>
<link rel="stylesheet" href="css/style.css" type="text/css" />
</head>
<body>
<script type="text/javascript">
	function newMember(){
		window.open(
			"signup.jsp","width=400,height=300"
		);
	}
</script>

<header>
	<h1>댓글과 대댓글 실습예제</h1>
</header>

<div id="wrapper">
	<nav>
		<ul>
			<li><a href="#">로고</a></li>
			<li><a href="javascript:newMember()">회원가입</a></li>
			<li><a href="controller.jsp?action=login">로그인</a></li>
		</ul>
	</nav>
	<section id="main">
		<h2>게시글 목록</h2>
      	<%-- datas내부의 boardVO에 접근 --%>
		<c:forEach var="bsList" items="${datas}">
		<c:set var="vo" value="${bsList.boardVO}" />
			<div class="board">
				<h3>[${vo.bid}] ${vo.mid} >> ${vo.content} [댓글수 ${vo.rpcnt} | 좋아요 ${vo.favcnt}] [${vo.bdate}]</h3>
			</div>
			<div class="reply">
				<form action="controller.jsp?action=newReply" method="post">
					<input type="text" name="msg">
					<input type="submit" value="댓글 작성하기">
				</form>
			</div>
			<div class="replylist">
           		 <%-- datas내부의 replyList에 접근 --%>
				<c:forEach var="r" items="${bsList.replyList}">
					<h4>${r.mid} >> ${r.msg} [${r.rdate}]</h4>
				</c:forEach>
			</div>
		</c:forEach>
	</section>
</div>

<footer>
	<p>ⓒCOPYRIGHT</p>
</footer>

</body>
</html>

 

 


 

3) controller

controller부분에서는 별다른 특이사항은 없으며, dao의 selectAll메서드를 사용할때 인자를 넣어주는 부분만 고려하면 된다.

<%@page import="model.vo.BoardSet"%>
<%@page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:useBean id="boardDAO" class="model.dao.BoardDAO"></jsp:useBean>    
<%
	String action=request.getParameter("action");

	if(action.equals("main")){
		
        //한 페이지에 3개씩 출력
		ArrayList<BoardSet> datas = boardDAO.selectAll(3);
		request.setAttribute("datas", datas);
		pageContext.forward("main.jsp");
		
	} else if(action.equals("login")){
		
	}else if(action.equals("newReply")){
		
	}else{
		
	}
%>

 

 

 


 

반응형