학원/JSP SERVLET

2022-01-12 model2 페이징, 댓글 수 표시 / 첨부파일 업로드

링규 2022. 1. 12. 15:45

 

https://omp14.tistory.com/76

 

페이징 

2. Paging 클래스에 paging() 메소드 생성 

 

private void paging() {
    //각 멤버 변수 값 세팅


    double temp = Math.ceil(page/(double)displayPage);
    endPage = (int)(temp * displayPage);
    beginPage = endPage - displayPage + 1 ;

    int totalPage = (int)Math.ceil(totalCount/(displayRow));
    //총 게시물 수를 한 화면에 표시할 게시물 수로 나눠서 총 페이지 갯수를 계산

    if(totalPage < endPage) {//총 페이지가 화면에 표시할 끝페이지보다 작다면
        endPage = totalPage;
        next = false;
    } else {
        next = true;
    }

    prev = (beginPage==1)? false:true;

    startNum = (page-1)*displayRow+1;
    //현재 화면의 시작 게시물 번호 : 1페이지-1, 2페이지-11, 3페이지-21 ...
    endNum = page*displayRow;
}

 

3. MainAction에 Paging객체 생성 + request.setAttribute("paging", paging); + 페이지 값 세팅

4. 전체 페이지 갯수를 알아내기 위해서 getAllCount() 메서드를 BoardDao에 생성

-> select count(*) ~~

5. MainAction에 글을 불러오는 ArrayList가 전체 글을 다 보여주는 것이 아니라 해당 페이지의 글만 표시해야 하므로 paging 처리 아래로 옮겨주고 selectBoard()메서드를 paging을 전달인수로 받는 selectBoard(paging)로 수정한다!! 

-> 앞으로 무조건 계속 페이징을 통해 표시할 것이므로 오버라이드가 아니라 아예 수정해버림

6. 글 번호는 삭제나 오류 때문에 연속되지 않으므로 쿼리 사용시 rownum을 사용하여야 한다.

 

select rownum, sub.* from (select * from board order by num desc) sub;
-- rownum과 *은 함께 사용할 수 없으므로 서브쿼리로 처리한다.

select * from 
(select rownum as rn, sub.* from (select * from board order by num desc) sub)  
where rn>=11 and rn<20; 
--원하는 rownum 범위만 골라냄 -> 게시물 갯수가 많아지면 명령의 실행 속도가 느려짐 

select * from 
(select * from 
(select rownum as rn, sub.* from (select * from board order by num desc) sub)  
where rn>=11) where rn<=20;
--범위를 좁혀서 검색 속도를 향상 시킴

 

7. 위 sql에 맞추어 selectBoard메소드 수정

 

public ArrayList<BoardDto> selectBoard(Paging paging){
    ArrayList<BoardDto> list = new ArrayList<>();
    //String sql = "select * from board order by num desc";
    String sql = "select * from " 
                +"(select * from " 
                + "(select rownum as rn, sub.* "
                + "from (select * from board order by num desc) sub) " 
                + "where rn>=?) where rn<=?";
    con = Dbman.getConnection();
    try {
        pstmt = con.prepareStatement(sql);
        pstmt.setInt(1,  paging.getStartNum());
        pstmt.setInt(2,  paging.getEndNum());
        rs = pstmt.executeQuery();
        while(rs.next()) {
            BoardDto bdto = new BoardDto();
            bdto.setNum(rs.getInt("num"));
            bdto.setUserid(rs.getString("userid"));
            bdto.setPass(rs.getString("pass"));
            bdto.setEmail(rs.getString("email"));
            bdto.setTitle(rs.getString("title"));
            bdto.setReadcount(rs.getInt("readcount"));
            bdto.setWritedate(rs.getTimestamp("writedate"));
            list.add(bdto);
        }
    } catch (SQLException e) { e.printStackTrace();
    } finally { Dbman.close(con, pstmt, rs); }

    return list;
}

 

8. main.jsp에 페이지 태그 추가

-> 만약 현재 보고 있는 페이지와 클릭한 페이지가 다르다면 클릭한 페이지로 이동

-> prev, next 표시 

 

<div id="paging" align="center" style="font-size:110%; font-wight:bold;">
    <!-- 페이지가 클릭될때마다 이동할 링크 기본 경로를 변수에 저장 -->
    <c:url var="action" value="board.do?command=main"/>
    <c:if test="${paging.prev}">
        <a href="${action}&page=${paging.beginPage-1}">◀</a>&nbsp;
        <!-- 링크되는 주소  : board.do?command=main&page=??-->
    </c:if>

    <!-- 실제 페이지들이 표시되는 곳 -->
    <c:forEach begin="${paging.beginPage}" end="${paging.endPage}" var="index">

        <c:choose>
            <c:when test="${paging.page==index}">
                <span style="color:red">${index}&nbsp;</span>
            </c:when>
            <c:otherwise>
                <a href="${action}&page=${index}">${index}</a> &nbsp;
            </c:otherwise>
        </c:choose>
    </c:forEach>

    <c:if test="${paging.next}">
        <a href="${action}&page=${paging.endPage+1}">▶</a>&nbsp;
    </c:if>
</div>

 

 

 

댓글 수 표시 

 

페이지에 보이는 게시글의 댓글 수만 불러올 것

 

1.board 테이블에 댓글 수를 저장할 replycnt 컬럼 생성

 

alter table board add replycnt number(3) default 0;

 

2. BoardDto에 replycnt 변수 선언하고 getter, setter 설정

3. 현제 replycnt 값은 전부 null이므로 작성된 댓글 수를 불러와야함

-> 게시물 번호를 전달인수로 댓글 수를 얻어오는 메소드 생성 

 

public int getReplycnt(int num) {
    int cnt = 0; 
    String sql = "select count(*) as cnt from reply where boardnum=?";
    con=Dbman.getConnection();
    try {
        pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, num);
        rs = pstmt.executeQuery();
        if(rs.next()) cnt = rs.getInt("cnt");
    } catch (SQLException e) {e.printStackTrace();
    } finally {Dbman.close(con, pstmt, rs);}
    return cnt;
}

 

4. main.jsp의 제목을 표시하는 태그 옆에 [댓글수] 추가 

-> 댓글 수가 0이면 표시하지 않음 

 

<td align="left"> &nbsp;&nbsp;
    <a href="board.do?command=boardView&num=${board.num}">
    ${board.title}
    <c:if test="${board.replycnt>0}">
        <span style="color:red; font-weight:bold;">
            [${board.replycnt}]
        </span>
    </c:if>
    </a>
</td>

 

 

댓글 수 생성 완료

 

게시판은 마무리 -> 전체 코드는 보호글 

 

 

첨부 파일 업로드 하기

 

1. 새로운 다이내믹웹프로젝트 생성 + project Facet, WEB-INF/lib에 jar파일 3개 넣기 

 

2. https://www.servlets.com/ 에 접속

 

클릭

 

밑으로 쭉 내려서 위 파일 다운로드

 

압축을 풀고 lib 파일 안에 있는 cos.jar를 WEB-INF/lib에 추가

 

 

3. 새로운 jsp파일 열기 

 

※파일 업로드 기능이 포함된 form은 반드시 enctype="multipart/form-data" 옵션을 추가 해야 함

method는 반드시 post일 것

 

<body>
<form action="upload.do" method="post" enctype="multipart/form-data">
	글쓴이 : <input type="text" name="name"><br>
	제 &nbsp; 목 : <input type="text" name="title"><br>
	파일 지정하기 : <input type="file" name="uploadFile"><br>
	<input type="submit" value="전송">
</form>
<!-- <img src="upload/jquery.jpg" width="300"/> -->
</body>

 

4. upload.do(UploadServlet) 만들기

doPost는 doGet(request, response); 이 상태로 내버려두고 doGet 수정

 

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");

    //1) 파일이 업로드 될 타겟 폴더 이름 저장 
    String savePath = "upload";

    //2) 업로드될 파일의 용량을 제한 지정
    int uploadFileSizeLimit=5*1024*1024; //5Mb

    //3) 인코딩 방식 저장
    String encType="UTF-8";

    //4) 업로드 될 서버의 실제 저장 장소
    ServletContext context = getServletContext();
    String uploadFilePath = context.getRealPath(savePath);
    
    //MultipartRequest 객체가 생성되는 순간 업로드 되는 파일은 해당 경로에 업로드 완료됨
    MultipartRequest multi = new MultipartRequest(request, uploadFilePath, 
	uploadFileSizeLimit, encType, new DefaultFileRenamePolicy());

    System.out.println("request로 처리 : " + request.getParameter("name"));
    System.out.println("multi로 처리 : " + multi.getParameter("name"));
    
    //jsp 파일의 form에서 전달된 파일의 이름 및 그 외 항목들을 파라미터로 추출
    String name = multi.getParameter("name");
    String title = multi.getParameter("title");
    String fileName = multi.getFilesystemName("uploadFile");
    
    request.setAttribute("name", name);
    request.setAttribute("title", title);
    request.setAttribute("fileName", fileName);

    RequestDispatcher dp = request.getRequestDispatcher("01_result.jsp");
    dp.forward(request,response);
}

 

 

* 1024byte=12Kbyte, 1024Kbyte=1Mb

 

※MultipartRequest는 cos.jar 안에 있는 파일 업로드에 중요한 역할을 하는 클래스.

 

- enctype="multipart/form-data"로 보낸 데이터들은 일반 request로 전달 받을 수 없으므로 MultipartRequest에 request를 넣어 사용할 수 있도록 설정

- DefaultFileRenamePolicy : 업로드 파일과 동일한 이름이 이미 존재하면 새 이름을 부여해주는 역할

 

 

전송을 누르면

 

콘솔 결과

 

 

5. 결과를 표시할 jsp파일 만들기

 

<body>
<h3>
글쓴이 : ${name}<br>
제목 : ${title}<br>
이미지 : <img src = "upload/${fileName}" width="200"/>
</h3>
</body>

 

전송을 누르면

 

 

 

이미지 주소를 복사해 보면

http://localhost:8090/WEB11_FileUpIoad/upload/E_ugmLCWUAAsuWk1.jpg 라고 나오는데 실제 경로의 upload 폴더에 가보면 파일이 해당 파일이 없다 

 

-> 실제로 파일이 업로드 되는 uploadFilepath를 출력해보면

워크스페이스경로\metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\WEB11_FileUpIoad\upload

 

 

경로대로 찾아가보면 여기에 파일이 저장되어 있다. 

->  같은 사진 파일들이 DefaultFileRenamePolicy에 의해 제목이 다르게 저장되었다.