위로 아래

글목록 HTML

자바스크립트를 이용해 각 제목의 <a> 태그를 클릭하면 <table> 태그 밑의 hidden input value에 a 태그의 input value 값을 넣고 submit해서,

제목을 클릭하면 각 줄마다의 bno 값을 다음 페이지로 전송한다.

 

조회수가 10이 넘어가면 hot.gif 이미지가 붙도록 설정한다.

답글일 경우엔 앞에 re.gif 이미지를 붙인다.

blevel로 몇 번째의 답글인지 표시하여 해당 답글만큼 level.gif 이미지의 크기를 늘려 더 크게 들여쓰기 한다.

 

jstl 태그 라이브러리 중 function을 이용해 게시글의 개수를 파악해 게시글이 없으면 없음을 띄운다.

jstl 태그 라이브러리 중 core를 이용하여 게시글을 forEach 반복문을 통해 나열한다.

 

또한, 페이지를 관리하는 박스를 제작하기 위해 jstl 라이브러리 중 core를 사용하여 전달 받은 페이지 개수만큼 forEach 반복문으로 페이지를 만들고, 

클릭 시 해당 페이지에 속하는 게시글만 뜨도록 현재 페이지인 p를 전달해 해당 페이지의 start와 end 변수를 구하도록 하여 쿼리문을 다루는 DAO에 전달한다.

페이지 이동 시에는 주소 뒤에 쿼리를 붙여 정보를 전달해준다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri = "http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri = "http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글 목록</title>
<link rel="stylesheet" type="text/css" href="css/list.css">
<script src="jquery/jquery-3.7.0.min.js"></script>
<script>
$().ready(function(){
	let $item = $('a.content').on("click",function(){
		let idx = $item.index(this);
		//alert($("a.content input[type=hidden]").eq(idx).val());
		
		var f = $('form[name=content]')
		$('form input[name=bno]').attr('value', $("a.content input[name=no]").eq(idx).val());
		f.attr('action','content.do');
		f.submit();
	});
})
</script>
</head>
<body>
<table>
	<thead>
		<tr>
			<th colspan="5"><h3>글 목록 보기 (전체 게시글 수 : ${totalCnt})</h3></th>
			<th><a href="writeForm.do">글쓰기</a></th>
		</tr>
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>최종 수정일</th>
			<th>조회수</th>
			<th>아이피</th>
		</tr>
	</thead>
	<tbody>
		<c:choose>
			<c:when test="${fn:length(articles)==0}">
				<tr><td colspan="6"><span>게시글이 없습니다.</span></td></tr>
			</c:when>
			<c:when test="${fn:length(articles)>0}">
				<c:forEach items="${articles}" var="article" varStatus="i">
					<tr>
						<td class="col1">${article.rn}</td>
						<td class="col2">
							<c:choose>
								<c:when test="${article.blevel==0}">
									<img src="image/level.gif" style="width:5px; height:10px;">
								</c:when>
								<c:when test="${article.blevel>0}">
									<img src="image/level.gif" width=${article.blevel*15}px>
									<img src="image/re.gif">
								</c:when>
							</c:choose>
							<a class="content">
								${article.subject}
								<input type="hidden" name="no" value="${article.bno}">
							</a>
						</td>
						<td class="col3">${article.writer}</td>
						<td class="col4">${article.regdate}</td>
						<td class="col5">
							${article.readcount}
							<c:if test="${article.readcount>10}">
								<img src="image/hot.gif" style="width:15px; height:10px;">
							</c:if>
						</td>
						<td class="col6">${article.ip}</td>
					</tr>
				</c:forEach>
			</c:when>
		</c:choose>
	</tbody>
	<tfoot>
		<tr>
			<td colspan="6" style="text-align:center">
				<c:forEach var="p" begin="1" end="${pageCnt}" step="1">
					<a href="list.do?p=${p}"><c:out value="${p}"/></a> &nbsp;
				</c:forEach>
			</td>
		</tr>
	</tfoot>
</table>
<form action="content.do" method="post" name="content">
	<input type="hidden" name="bno" value="${article.bno}">
</form>
</body>
</html>

 

 

글목록 CSS

@charset "UTF-8";
*{margin:0; padding: 0;}
table {border:1px solid black; border-collapse: collapse; width:90%; margin:0 auto;}
th, td {border:1px solid black; border-collapse: collapse; padding:10px; margin:5px;}
th {background-color: #cfcfff;}
td {background-color: #ffffff; font-weight: 200;}
.btn {height:30px; width:850px; text-align:right;}
a {color:black; text-decoration: none; }
a:hover {font-weight: bold;}
.col1 {width:8%;}
.col2 {width:35%;}
.col3 {width:20%;}
.col4 {width:15%;}
.col5 {width:10%;}
.col6 {width:12%;}
span {text-align: center;}

 

 

글목록 ACTION

한 페이지에 들어올 게시글 개수는 언제든지 바뀔 수 있으니까 따로 빼주어서 사용한다.

인터페이스를 작성하여 final과 대문자 변수명을 사용해 상수를 선언한다.

package model;

public interface PageBean {
	final int LINE_OF_PAGE = 5;
}

 

 

현재 페이지 변수를 선정하고 처음엔 1로 초기화해준다. 

전체 게시글 수와, 

전체 페이지 수,

그리고 페이지마다 시작하는 게시글의 번호와 마지막 게시글의 번호를 작성한다.

시작하는 게시글 번호 변수인 start는, '이전 페이지 수 * 페이지당 게시글 수'로 구하고,

마지막 게시글 번호 변수인 End는, 

'최종 게시글 수 >= 현재 페이지 수 * 페이지당 게시글 수'일 경우엔 '현재 페이지수 * 페이지당 게시글 수'가 되도록 하고,

'최종 게시글 수 <= 현재 페이지 수 * 페이지당 게시글 수'일 경우엔 '최종 게시글 수'가 되도록 한다. 

 

start와 end는 DAO에 전달해, 쿼리문에서 페이지마다의 게시글을 불러오도록 하는 데에 사용될 것이고,

나머지 변수들은 view 역할을 하는 jsp 문서에 전달될 것이다.

package action;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import model.BoardDAO;
import model.BoardDTO;
import model.PageBean;

public class ListAction implements CommandAction {

	@Override
	public String requestProc(HttpServletRequest request, HttpServletResponse response) throws Exception {
		BoardDAO dao = BoardDAO.getInstance();
		
		int currentPage = 1;
		int totalCnt = dao.getTotalCnt();
		
		// p가 이미 있을 때 글목록 버튼을 누르면 해당 페이지로 갈 수 있도록 currentPage에 ListView 페이지의 p값을 대입.
		// p가 없을 경우 위의 초기화에서 currentPage=1준 것을 쓴다.
		if(request.getParameter("p") != null) {
			currentPage = Integer.parseInt(request.getParameter("p"));
		}
		
		int start = (currentPage-1)*PageBean.LINE_OF_PAGE + 1;
		int end = (currentPage*PageBean.LINE_OF_PAGE >= totalCnt) ? totalCnt : currentPage*PageBean.LINE_OF_PAGE;
		
		int pageCnt=1;
		if(totalCnt%PageBean.LINE_OF_PAGE == 0) pageCnt = totalCnt/PageBean.LINE_OF_PAGE;
		else pageCnt = totalCnt/PageBean.LINE_OF_PAGE + 1;
		
		List<BoardDTO> articles = dao.getArticles(start,end);
		
		request.setAttribute("p", currentPage);
		request.setAttribute("totalCnt", totalCnt);
		request.setAttribute("articles", articles);
		request.setAttribute("pageCnt", pageCnt);
		
		return "view/ListView.jsp?p="+currentPage;
	}

}

 

 

 

 

 

글목록 DAO

key 역할을 하는 bno의 개수를 구함으로써 전체 게시글 수를 알아낸다.

전체 게시글 수는 페이지 박스를 제작하기 위해 필수이다.

public int getTotalCnt() {
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    int result = 0;

    try {
        conn = DBConnector.getInstance().getConnection();
        String sql = "SELECT COUNT(bno) AS cnt FROM board";
        pstmt = conn.prepareStatement(sql);
        rs = pstmt.executeQuery();
        if(rs.next()) {
            result = rs.getInt("cnt");
        }

    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {
            if(conn!=null) conn.close();
            if(pstmt!=null) pstmt.close();
            if(rs!=null) rs.close();
        } catch(SQLException e) {e.printStackTrace();}
    }
    return result;
}

 

게시글은 페이지마다 해당되는 게시글만 불러오도록 해야한다.

필요한 계산은 DAO가 아닌, action에서 하고, 계산을 한 start와 end를 인자로 받아와 쿼리문에 반영하도록 한다.

public List<BoardDTO> getArticles(int start, int end) {
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    List<BoardDTO> articles = new ArrayList<BoardDTO>();

    try {

        conn = DBConnector.getInstance().getConnection();
        String sql = "SELECT * FROM("
					+ "SELECT ROW_NUMBER() "
					+ "OVER(ORDER BY bref DESC, bno, bstep) AS rn, "
					+ "bno, bref, bstep, blevel, readcount, "
					+ "subject, content, writer, regdate, ip, passwd "
					+ "FROM board) t "
					+ "WHERE rn >= ? AND rn <= ?";
        pstmt = conn.prepareStatement(sql);
        pstmt.setInt(1, start);
        pstmt.setInt(2, end);
        rs = pstmt.executeQuery();

        while(rs.next()) {
            BoardDTO article = new BoardDTO();
            article.setRn(rs.getInt("rn"));
            article.setBno(rs.getInt("bno"));
            article.setBref(rs.getInt("bref"));
            article.setBstep(rs.getInt("bstep"));
            article.setBlevel(rs.getInt("blevel"));
            article.setReadcount(rs.getInt("readcount"));
            article.setSubject(rs.getString("subject"));
            article.setContent(rs.getString("content"));
            article.setWriter(rs.getString("writer"));
            article.setRegdate(rs.getString("regdate"));
            article.setIp(rs.getString("ip"));
            article.setPasswd(rs.getString("passwd"));
            articles.add(article);
        }

    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if(conn!=null) conn.close();
            if(pstmt!=null) pstmt.close();
            if(rs!=null) rs.close();
        } catch (SQLException e) {e.printStackTrace();}
    }

    return articles;
}

 

 

완성 모습

페이지 박스도, 이미지 적용과 답글이 잘 적용되는 것도 확인할 수 있다.