반응형
이 포스팅의 목차는 다음과 같다.
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{
}
%>
반응형
'JSP' 카테고리의 다른 글
[게시판 Ver.2] 내가 쓴 글 목록 보기 (0) | 2022.03.16 |
---|---|
[게시판 Ver.2] 커스텀태그_응용 (0) | 2022.03.15 |
[JDBC] MVC나누기 3_게시판+FC,필터,리스너 (0) | 2022.03.11 |
[controller업그레이드] 리스너 & 필터_(크롤링 & 인코딩) (0) | 2022.03.10 |
[controller업그레이드] 서블릿 활용 (0) | 2022.03.08 |