[JSP] 게시판 (1)
2024. 10. 7. 18:25ㆍJSP
오늘은 회원과 게시판 기능을 함께 합쳐서 만들어 보자.
Member 테이블
컬럼명 | null 여부 | 데이터 타입 | |
IDX | NOT NULL | NUMBER | primary key |
USERID | NOT NULL | VARCHAR2(100) | unique |
USERPW | NOT NULL | VARCHAR2(500) | |
USERNAME | NOT NULL | VARCHAR2(100) | |
NOT NULL | VARCHAR2(100) | ||
GENDER | VARCHAR2(50) |
Board 테이블
컬럼명 | null 여부 | 데이터 타입 | 참조 | |
IDX | NOT NULL | NUMBER | primary key | |
TITLE | NOT NULL | VARCHAR2(500) | ||
WRITER | NOT NULL | VARCHAR2(100) | member 테이블의 userid 참조 | |
CONTENT | NOT NULL | VARCHAR2(4000) | ||
WRITEDATE | DATE |
MemberDTO & BoardDTO
getter, setter를 생성해 준다.
BoardDAO
게시판 기능을 처리해줄 함수들 작성.
public class BoardDAO {
private Connection conn;
private PreparedStatement pstmt;
private ResultSet rs;
private Context init;
private DataSource ds;
private static BoardDAO instance = new BoardDAO();
public static BoardDAO getInstance() {
return instance;
}
private BoardDAO() {
try {
init = new InitialContext();
ds = (DataSource) init.lookup("java:comp/env/jdbc/oracle");
} catch (NamingException e) {
e.printStackTrace();
}
}
private void close() {
try {
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(conn != null) conn.close();
}catch(SQLException e) {}
}
private BoardDTO mapping(ResultSet rs) throws SQLException {
BoardDTO dto = new BoardDTO();
dto.setContent(rs.getString("content"));
dto.setIdx(rs.getInt("idx"));
dto.setTitle(rs.getString("title"));
dto.setWriteDate(rs.getDate("writeDate"));
dto.setWriter(rs.getString("writer"));
return dto;
}
// 게시글 목록
public List<BoardDTO> selectList() {
ArrayList<BoardDTO> list = new ArrayList<>();
String sql = "select "
+ " (select count(*) from reply where board_idx = board.idx) as replyCount,"
+ " board.* "
+ " from board order by idx desc"; // 최신글이 위에 노출되도록
try {
conn = ds.getConnection();
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()) {
BoardDTO dto = mapping(rs); // 기본 맵핑 +
dto.setReplyCount(rs.getInt("replyCount")); // 댓글 개수
list.add(dto);
}
} catch (SQLException e) {
e.printStackTrace();
} finally { close(); }
return list;
}
// 게시글 조회
public BoardDTO selectOne(int idx) {
BoardDTO dto = null;
String sql = "select * from board where idx = ?";
try {
conn = ds.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, idx);
rs = pstmt.executeQuery();
while(rs.next()) {
dto = mapping(rs);
}
} catch (SQLException e) {
e.printStackTrace();
} finally { close(); }
return dto;
}
// 게시글 작성
public int insert(BoardDTO dto) {
int row = 0;
String sql = "insert into board (title, writer, content) "
+ " values (?, ?, ?)";
try {
conn = ds.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, dto.getTitle());
pstmt.setString(2, dto.getWriter());
pstmt.setString(3, dto.getContent());
row = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally { close(); }
return row;
}
}
header.jsp
모든 페이지에 적용할 태그 선인 및 링크 등을 작성해준다.
다른 모든 페이지들에 include하여 사용.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="member.*, board.*, reply.*" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="cpath" value="${pageContext.request.contextPath }" />
<c:set var="memberDAO" value="${MemberDAO.getInstance() }" />
<c:set var="boardDAO" value="${BoardDAO.getInstance() }" />
<c:set var="replyDAO" value="${ReplyDAO.getInstance() }" />
<% request.setCharacterEncoding("UTF-8"); %>
<% response.setCharacterEncoding("UTF-8"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>day16 - board</title>
</head>
<body>
<header>
<h1><a href="${cpath }">day16 - board</a></h1>
<div style="text-align: right; padding-right: 20px; height: 30px;">
${login.userid }
</div>
<nav>
<ul style="display: flex; list-style: none; justify-content: space-around;">
<li><a href="${cpath }/login.jsp">로그인</a></li>
<li><a href="${cpath }/logout.jsp">로그아웃</a></li>
<li><a href="${cpath }/join.jsp">회원가입</a></li>
<li><a href="${cpath }/board.jsp">게시판</a></li>
</ul>
</nav>
</header>
board.jsp
boardDAO에 있는 selectList() 함수를 이용하여 게시판 목록을 보여준다.
c:forEach를 이용하여 게시글을 1개씩 보여줄 수 있도록 한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="header.jsp" %>
<h3>게시판</h3>
<table border="1" cellpadding="10" cellspacing="0" width="800" align="center">
<c:set var="list" value="${boardDAO.selectList() }" />
<c:forEach var="dto" items="${list }">
<tr>
<td>${dto.idx }</td>
<td width="500">
<a href="${cpath }/view.jsp?idx=${dto.idx}">${dto.title }</a>
<c:if test="${dto.replyCount != 0 }">
<span style="color: red;
font-size: 13px;">[${dto.replyCount }]</span>
</c:if>
</td>
<td>${dto.writer }</td>
<td>${dto.writeDate }</td>
</tr>
</c:forEach>
</table>
<div style="display: flex; width: 800px; margin: 20px auto; justify-content: space-between;">
<div>
</div>
<div>
<a href="${cpath }/write.jsp"><button>작성</button></a>
</div>
</div>
</body>
</html>
write.jsp
만약 메서드가 GET이면서 로그인이 되어 있지 않는 상태라면, alert으로 '로그인 후 작성 가능' 을 띄우고 login.jsp로 이동 시킨다.
form에 mothod를 POST로 하고, form을 작성하게 한다.
form을 제출하면 boardDAO에 있는 insert() 함수를 이용하여 게시글을 추가로 생성한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="header.jsp" %>
<c:if test="${pageContext.request.method == 'GET' }">
<c:if test="${empty login }">
<script>
alert("먼저 로그인 후 글을 작성할 수 있습니다")
location.href = '${cpath}/login.jsp'
</script>
</c:if>
<form method="POST">
<p><input type="text" name="title" placeholder="제목" required autofocus></p>
<input type="hidden" name="writer" value="${login.userid }">
<p>
<textarea name="content" placeholder="내용" rows="8" cols="60" required></textarea>
</p>
<p><input type="submit" value="작성하기"></p>
</form>
</c:if>
<c:if test="${pageContext.request.method == 'POST' }">
<jsp:useBean id="dto" class="board.BoardDTO" />
<jsp:setProperty property="*" name="dto"/>
<c:set var="row" value="${boardDAO.insert(dto) }" />
<c:redirect url="/board.jsp" />
</c:if>
</body>
</html>
view.jsp
게시글 상세 보기
boardDAO에 있는 selectOne() 함수를 이용하여 특정된 1개의 게시물을 볼 수 있도록 한다.
각 게시물 밑에는 form을 위치시킨다. (댓글)
<h3>게시글 상세 보기</h3>
<fieldset>
<c:set var="dto" value="${boardDAO.selectOne(param.idx) }" />
<h4>${dto.title } | ${dto.writer } | ${dto.writeDate }</h4>
<pre>${dto.content }</pre>
</fieldset>
<br>
<form method="POST" action="reply-write.jsp">
<h3>댓글 작성</h3>
<c:if test="${empty login }">
<c:set var="replyComment">로그인 후에 댓글 작성 가능합니다</c:set>
</c:if>
<c:if test="${not empty login }">
<c:set var="replyComment">바르고 고운 말을 사용합시다</c:set>
</c:if>
<div style="display: flex; align-items: center;">
<textarea name="content" rows="5" cols="80"
placeholder="${replyComment }" ${empty login ? 'disabled' : '' }
style="resize: none;
height: 100px;
padding: 10px;
box-sizing: border-box;"></textarea>
<input type="submit" value="댓글쓰기"
${empty login ? 'disabled' : '' }
style="margin: 10px;
height: 100px;">
</div>
<input type="hidden" name="board_idx" value="${param.idx }">
<input type="hidden" name="writer" value="${login.userid }">
</form>
<div id="reply">
<c:forEach var="reply" items="${replyDAO.selectList(param.idx) }">
<div class="replyItem" style="border: 1px solid grey;
margin: 20px;
padding: 10px;
box-sizing: border-box;">
<div style="display: flex; justify-content: space-between;">
<div>${reply.writer }</div>
<div><fmt:formatDate value="${reply.writeDate }" pattern="yyyy-MM-dd a hh:mm" /></div>
</div>
<div>
<pre>${reply.content }</pre>
<c:if test="${reply.writer == login.userid }">
<a href="${cpath }/reply-delete.jsp?idx=${reply.idx}&board_idx=${dto.idx}">
<button>댓글 삭제</button>
</a>
</c:if>
</div>
</div>
</c:forEach>
</div>
</body>
</html>
이제 제법 사이트라고 할 만한 것들을 만들게 되니까 더 재밌어진다.
자바와 html, DB 3개를 연동 하는 것이 익숙해지도록 전체 틀을 먼저 이해하는 것이 중요하다.
'JSP' 카테고리의 다른 글
[JSP] MVC (1) | 2024.10.09 |
---|---|
[JSP] 게시판 (2) (1) | 2024.10.07 |
[JSP] 회원 기능 (2) (0) | 2024.10.07 |
[JSP] 회원 기능 (1) (0) | 2024.10.05 |
[JSP] Login Session (1) | 2024.10.05 |