국비교육(22-23)

35일차(3)/jsp(23) : 게시판 조회수 기능, 페이징 처리 기능 구현

서리/Seori 2022. 11. 27. 01:41

35일차(3)/jsp(23) : 게시판 조회수 기능, 페이징 처리 기능 구현

 

- 조회수 기능 구현

- 게시판 페이징 처리

 

 

- 글 자세히 보기(detail.jsp) 페이지에 들어가면 viewCount의 숫자가 늘어나도록 코딩하면 된다.

 

<CafeDao> - 조회수를 올리는 메소드 addViewCount 추가

//글의 조회수를 올리는 메소드
public boolean addViewCount(int num) {		
    Connection conn = null;
    PreparedStatement pstmt = null;
    int rowCount = 0;
    try {
        conn = new DbcpBean().getConn();
        String sql = "UPDATE board_cafe"
                + " SET viewCount=viewCount+1"
                + " WHERE num=?";
        pstmt = conn.prepareStatement(sql);
        //?에 바인딩
        pstmt.setInt(1, num);
        //INSERT or UPDATE or DELETE문을 수행하고 수정,삭제,추가된 row의 개수 리턴
        rowCount = pstmt.executeUpdate();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (pstmt != null)
                pstmt.close();
            if (conn != null)
                conn.close();
        } catch (Exception e2) {
        }
    }

    if (rowCount > 0) {
        return true;
    } else {
        return false;
    }
}

 

 

- sql문에서도 위와 같은 연산처리가 가능!

 

CafeDao.getInstance().addViewCount(num);

- detail.jsp에도 한줄 추가! detail.jsp가 실행될 때마다 addViewCount 메소드가 실행되며 조회수가 늘어나도록 처리한 것!

 

- 게시물 클릭시 조회수가 증가된 것이 확인된다.

 


 

- list에 bootstrap css를 적용하고, 페이징 처리

 

 

- 전체 글의 갯수를 리턴하는 메소드 만들기

 

SELECT MAX(ROWNUM) AS num FROM board_cafe

- 전체 글의 갯수는 현재 작성된 데이터의 ROWNUM 중에서 가장 큰 값을 가져오면 된다.

 

 

- getList의 인자로 dto를 받아오도록 메소드 수정

- dto를 생성한 후, startRowNum, endRowNum을 dto에 저장해서

 해당 rownum에 해당하는 데이터만 list로 출력해주도록 수정!

 

 

<CafeDao>에 getCount 메소드 추가

//글의 갯수를 리턴하는 메소드
public int getCount() {
    int count=0;
    //필요한 객체를 담을 지역변수를 미리 만들어둔다.
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
        //Connection Pool에서 Connection 객체를 하나 얻어온다.
        conn = new DbcpBean().getConn();
        //실행할 sql문의 뼈대 구성하기
        String sql = "SELECT MAX(ROWNUM) AS num "
                + " FROM board_cafe";
        //sql문의 ?에 바인딩할게 있으면 한다.

        pstmt = conn.prepareStatement(sql);
        //SELECT문을 수행하고 결과값을 받아온다.
        rs = pstmt.executeQuery();
        //반복문 돌면서 resultSet에서 필요한 값을 얻어낸다.
        if (rs.next()) {
            count=rs.getInt("num");
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (rs != null)
                rs.close();
            if (pstmt != null)
                pstmt.close();
            if (conn != null)
                conn.close(); //Connection Pool에 Connection 반납하기

        } catch (Exception e2) {
        }
    }
    return count;
}

- Rownum을 계산하여 숫자 값을 리턴하는 메소드 만들기

 


 

SELECT *
FROM
	(SELECT result1.*, ROWNUM AS rnum
	FROM 
		(SELECT num, writer, title, viewCount, regdate 
		FROM board_cafe
		ORDER BY DESC) result1)
WHERE rnum BETWEEN ? AND ?

- 정렬된 데이터(result1)에 ROWNUM을 부여하고,

 그 result1 테이블의 일정 범위 안에 있는 값만 출력되도록 하는 sql문

 

- result1.* : result1 테이블에 있는 모든 내용!

 

 

TO_CHAR(regdate, 'YYYY.MM.DD HH24:MI') AS regdate

- 편리한 사용을 위해 regdate를 문자 처리해주기

 

 

<Dao>의 getList 수정하기 (startRowNum, endRowNum을 세팅하는 sql문으로 수정)

//글 목록 리턴하기	
public List<CafeDto> getList(CafeDto dto) {
    //회원 목록을 담을 객체 생성
    List<CafeDto> list = new ArrayList<>();

    //필요한 객체를 담을 지역변수를 미리 만들어둔다.
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
        //Connection Pool에서 Connection 객체를 하나 얻어온다.
        conn = new DbcpBean().getConn();
        //실행할 sql문의 뼈대 구성하기
        String sql = "SELECT *"
                + " FROM"
                + "	(SELECT result1.*, ROWNUM AS rnum"
                + "	FROM "
                + "		(SELECT num, writer, title, viewCount, TO_CHAR(regdate, 'YYYY.MM.DD HH24:MI') AS regdate"
                + "		FROM board_cafe"
                + "		ORDER BY num DESC) result1)"
                + " WHERE rnum BETWEEN ? AND ?";
        //sql문의 ?에 바인딩할게 있으면 한다.
        pstmt = conn.prepareStatement(sql);
        pstmt.setInt(1,	dto.getStartRowNum());
        pstmt.setInt(2, dto.getEndRowNum());
        //SELECT문을 수행하고 결과값을 받아온다.
        rs = pstmt.executeQuery();
        //반복문 돌면서 resultSet에서 필요한 값을 얻어낸다.
        while (rs.next()) {
            CafeDto tmp=new CafeDto();
            tmp.setNum(rs.getInt("num"));
            tmp.setWriter(rs.getString("writer"));
            tmp.setTitle(rs.getString("title"));
            tmp.setViewCount(rs.getInt("viewCount"));
            tmp.setRegdate(rs.getString("regdate"));
            //CafeDto 객체의 참조값을 List 에 누적 시키기
            list.add(tmp);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (rs != null)
                rs.close();
            if (pstmt != null)
                pstmt.close();
            if (conn != null)
                conn.close(); //Connection Pool에 Connection 반납하기

        } catch (Exception e2) {
        }
    }
    return list;
}

 

 

<list.jsp>

<%@page import="test.cafe.dto.CafeDto"%>
<%@page import="test.cafe.dao.CafeDao"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%	
	//한 페이지에 몇개씩 표시한 것인지
	final int PAGE_ROW_COUNT=5;
	//하단 페이지를 몇개씩 표시할 것인지
	final int PAGE_DISPLAY_COUNT=5;
	
	//보여줄 페이지의 번호를 일단 1이라고 초기값 지정	
	int pageNum=1;
	
	//페이지 번호가 파라미터로 전달되는지 읽어와 본다.
	String strPageNum=request.getParameter("pageNum");
	//만일 페이지 번호가 파라미터로 넘어온다면
	if(strPageNum != null){
		//숫자로 바꿔서 보여줄 페이지 번호로 지정한다.
		pageNum=Integer.parseInt(strPageNum);
	}
	
	//보여줄 페이지의 시작 ROWNUM
	int startRowNum=1+(pageNum-1)*PAGE_ROW_COUNT;
	//보여줄 페이지의 끝 ROWNUM
	int endRowNum=pageNum*PAGE_ROW_COUNT;
	
	//하단 시작 페이지 번호
	int startPageNum=1+((pageNum-1)/PAGE_DISPLAY_COUNT)*PAGE_DISPLAY_COUNT;
	//하단 끝 페이지 번호
	int endPageNum=startPageNum+PAGE_DISPLAY_COUNT-1;
	//전체 글의 갯수
	int totalRow=CafeDao.getInstance().getCount();
	//전체 페이지의 갯수 구하기
	int totalPageCount=(int)Math.ceil(totalRow/(double)PAGE_ROW_COUNT);
	//끝 페이지번호가 이미 전체 페이지 갯수보다 크게 계산되었다면 잘못된 값이다.
	if(endPageNum>totalPageCount){
		endPageNum=totalPageCount; //끝 페이지번호 값을 보정해준다.
	}
	
	//CafeDto 객체를 생성해서
	CafeDto dto=new CafeDto();
	//위에서 계산된 startRowNum, endRowNum을 담고
	dto.setStartNum(startRowNum);
	dto.setEndRowNum(endRowNum);
	//CafeDto를 인자로 전달해서 글목록 얻어오기
	List<CafeDto> list=CafeDao.getInstance().getList(dto);
		
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/cafe/list.jsp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</head>
<body>
	<div class="container">
		<a href="${pageContext.request.contextPath }/cafe/private/insertform.jsp">새글 작성</a>
		<h3>카페 글 목록입니다.</h3>
		<table class="table table-striped">
			<thead class="table-info">
				<tr>
					<th>글번호</th>
					<th>작성자</th>
					<th>제목</th>
					<th>조회수</th>
					<th>작성일</th>
				</tr>				
			</thead>
			<tbody>
				<%for(CafeDto tmp:list) {%>
					<tr>
						<td><%=tmp.getNum() %></td>
						<td><%=tmp.getWriter() %></td>
						<td>
							<a href="detail.jsp?num=<%=tmp.getNum() %>"><%=tmp.getTitle() %></a>
						</td>
						<td><%=tmp.getViewCount() %></td>
						<td><%=tmp.getRegdate() %></td>
					</tr>
				<%} %>
			</tbody>		
		</table>	
		<nav>
			<ul class="pagination justify-content-center">
				<%if(startPageNum !=1) {%>
					<li class="page-item">
						<a class="page-link" href="list.jsp?pageNum=<%=startPageNum-1%>">Prev</a>
					</li>
				<%} %>				
				<%for(int i=startPageNum; i<=endPageNum; i++) {%>
					<li class="page-item <%=pageNum == i ? "active" : "" %>">
						<a class="page-link" href="list.jsp?pageNum=<%=i %>"><%=i %></a>
					</li>				
				<%} %>
				<%-- 마지막 페이지 번호가 전체 페이지의 갯수보다 작으면 Next링크를 제공한다. --%>
				<%if(endPageNum< totalPageCount) {%>
					<li class="page-item">
						<a class="page-link" href="list.jsp?pageNum=<%=endPageNum+1%>">Next</a>
					</li>
				<%} %>
			</ul>
		</nav>
	</div>
</body>
</html>

 

- startRowNum, endRowNum에 각각의 계산식 넣어주기

 

- 하단에 <nav>요소 추가해주고, 페이지 번호를 <li> 형태로 작성한다.

- for문을 돌면서 페이지번호를 출력해준다.

(i의 최소값은 startPageNum, 최대값은 endPageNum으로 지정하면 된다.)

- for문의 i 값을 사용해서 bootstrap css의 active효과를 줄 페이지 번호도 지정하기.

 

 

- 게시판 페이징 처리와 테이블 css까지 적용!