IDE & Framework/분류중

JSP 페이징된 게시판 만들기

Greensky0026 2021. 5. 30. 10:50
반응형

서론

 이번에 진행한 JSP 프로젝트가 다른팀에 비해서 인원이 한명 많았긴 했지만...

다들 이것저것 넣고싶은걸 추가하다 보니 정말 볼륨이 엄청났었습니다 ㅋㅋㅋ...

덕분에 다들 잠도 줄여가면서 플젝기간 내내 피곤에 쩔어 살았었죠

 

 여튼, 그렇게 설계가 되고나서... 저도 JSP는 처음 해보지만 PHP로는 이미 웹사이트를 구축해봤으니

팀원들의 고민과 시간단축을 위해 공통기능들을  변형해서 적용만 하게끔 일종의 프로토타입 소스를 제작해서 제공했습니다.

결과적으로 대성공해서 시간단축에 많은 도움이 되었었는데, 이번에 포스팅하는 소스가 바로 그 소스입니다 ㅎ...

주석을 엄청 상세하게 달아둿기 때문에 설명은 주석으로 대체하겠습니다.

 

 해당 소스는 DB의 글을 조회만 할 수 있으며 작성 및 수정 삭제는 불가능합니다.

 

 프로그램의 디자인 구조는 MVC Model2로 구현되어 있구요

사용한 db도 파일첨부 해 두겠습니다.

pagingDatas.sql
0.00MB

 깃이 더 편하시다면 아래 링크로 가셔서 보시면 되겠습니다!

https://github.com/gr2nsky/ProtoType/tree/main/java_Paging

 

gr2nsky/ProtoType

Contribute to gr2nsky/ProtoType development by creating an account on GitHub.

github.com

 

 쿼리가 이해가 잘 안가신다면 제가 포스팅해둔 글이 있으니

https://greensky0026.tistory.com/126 로 가셔서 한번 보시면 좋을듯 합니다

 

구성

  • HomeController.java
  • Dao.java
  • Dto.java
  • ContentCommand.java
  • ListCommand.java
  • list.jsp
  • content.jsp

 

 

소스 상세

 

Controller

@WebServlet("*.do")
public class homeController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public homeController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("<<<<< DoGet() >>>>>");
		actionDo(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("<<<<< DoGet() >>>>>");
		actionDo(request, response);
	}
	
	
	private void actionDo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("<<<actionDo()>>>");
		String uri = null;
		String conPath = null;
		String com = null;
		String viewPage = null;
		Command command = null;
		
		request.setCharacterEncoding("utf-8");
		
		uri = request.getRequestURI();
		conPath = request.getContextPath();
		com = uri.substring(conPath.length());
		System.out.println("<Request com : " + com + ">");
		
		switch (com) {
		case "/list.do":
			command = new ListCommand();
			command.excute(request, response);
			viewPage = "list.jsp";
			break;
			
		case "/content.do":
			command = new ContentCommand();
			command.excute(request, response);
			viewPage = "content.jsp";
			break;
		}
		
		RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
		dispatcher.forward(request, response);

	}

}

 

DTO (bean)

public class Dto {
	int no;
	String writer;
	String title;
	String content;
	Timestamp date;
	
	public Dto(){}

	public Dto(int no, String name, String title, String content, Timestamp date) {
		super();
		this.no = no;
		this.writer = name;
		this.title = title;
		this.content = content;
		this.date = date;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public Timestamp getDate() {
		return date;
	}
	public void setDate(Timestamp date) {
		this.date = date;
	}
}

 

ListCommand

public class ListCommand implements Command {
	
	//페이지당 표시할 게시글의 수
	int numOfTuplesPerPage = 5;

	@Override
	public void excute(HttpServletRequest request, HttpServletResponse response) {
		//사용자가 요청한 페이지 번호 초기값은 가장 최신글을 보여주는 1
		int requestPage = 1;
		Dao dao = new Dao();
		HttpSession session = request.getSession();
		
		//최초 목록 진입시 page값을 넘겨주지 않음 -> 초기값인 1페이지 목록을 보여줌
		//목록에서 page요청 -> 해당 페이지 번호로 requestPage 설정
		if ( request.getParameter("page") != null) {
			requestPage = Integer.parseInt(request.getParameter("page"));
			//content에서 목록보기 요청시 최근 페이지 목록으로 돌아가기 위해 세션에 저
			session.setAttribute("courrentPage", requestPage);
		}
		
		//반환되는 총 튜플의 수
		int countedTuple = dao.countTuple();
		//페이지 목록 (1...n)
		ArrayList<Integer> pageList = calcNumOfPage(countedTuple);
		//페이지 목록을 세션에 담는다. *list에 진입하면 무조건 세션이 갱신되므로 새 글이 생겨도 최신화가 된다.
		session.setAttribute("pageList", pageList);
		//해당 페이지에 알맞은 번호의 게시글
		ArrayList<Dto> dtos = dao.list(requestPage, numOfTuplesPerPage);
		//request에 게시글들을 태워 보낸다.
		request.setAttribute("list", dtos);
	}
	
	//총 튜플수를 받아 페이지당 표시할 게시글의 수로 나누어서 페이지수를 계산하고 jsp에서 for-each문을 돌리기 위해 배열에 담는다
	public ArrayList<Integer> calcNumOfPage(int countedTuple) {
		ArrayList<Integer> arr = new ArrayList<Integer>();
		int calcPage = 0;
		// 튜플의 총 갯수가 딱 맞아떨어지는 경우를 대비해 조건분기
		if (countedTuple % numOfTuplesPerPage == 0) {
			calcPage = countedTuple / numOfTuplesPerPage;
		} else {
			calcPage = countedTuple / numOfTuplesPerPage + 1;
		}
		
		for (int i = 1; i <= calcPage; i++) {
			System.out.println(i);
			arr.add(i);
		}
		return arr;
	}

}

 

ContentCommand

public class ContentCommand implements Command {

	@Override
	public void excute(HttpServletRequest request, HttpServletResponse response) {
		int no = Integer.parseInt(request.getParameter("no"));
		
		Dao dao = new Dao();
		Dto dto = dao.content(no);
		
		request.setAttribute("content", dto);

	}

}

 

DAO

public class Dao {
	
	DataSource dataSource;
	
	public Dao() {
		System.out.println("Connectiong database...");
		try {
			Context context = new InitialContext();
			dataSource = (DataSource)context.lookup("java:comp/env/jdbc/paging");
			System.out.println("Database connection success");
		} catch (NamingException e) {
			System.out.println("Database connection failed");
			e.printStackTrace();
		}
	}
	//사용자가 요청한 페이지(offset)와 페이지당 표시할 게시글의 수(limit)을 매개변수로 받는다.
	public ArrayList<Dto> list(int requestPage, int numOfTuplePerPage){
		Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		ArrayList<Dto> dtos = new ArrayList<Dto>();
		// LIMIT {OFFSET}, {LIMIT} -> 쿼리결과중 offset번째부터 limit개의 튜플을 출력  
		String query = "SELECT * FROM paging ORDER BY no DESC LIMIT ?, ?";
		//page는 1부터 시작하지만, offset은 0부터 시작.(0~9(10개), 10~19(10개)와같이 offset을 설정해야 하기 때문)
		int offset = requestPage - 1;
		
		try {
			conn = dataSource.getConnection();
			psmt = conn.prepareStatement(query);
			// 0을 나누면 에러가 발생하므로 예외처
			if (offset  == 0) {
				psmt.setInt(1, offset);
			} else {
				psmt.setInt(1, offset*numOfTuplePerPage);
			}
			psmt.setInt(2, numOfTuplePerPage);
			rs = psmt.executeQuery();
			
			while(rs.next()) {
				int no = rs.getInt("no");
				String writer = rs.getString("writer");
				String title = rs.getString("title");
				String content = rs.getString("content");
				Timestamp date = rs.getTimestamp("date");
				
				Dto dto = new Dto(no, writer, title, content, date);
				dtos.add(dto);
				System.out.println("list-data load success");
			}			
		} catch (Exception e) {
			System.out.println("list-data load fail");
			e.printStackTrace();
		} finally {
			try {
				if(rs != null) rs.close();
				if(psmt != null) psmt.close();
				if(conn != null) conn.close();
				System.out.println("< rs, psmt, conn close success>");
			} catch (Exception e) {
				System.out.println("< rs, psmt, conn close Fail>");
			}
		}
		
		return dtos;
	}
	//list에서 사용하는 릴레이션이 가진 튜플의 총 갯수를 리턴한다.
	public int countTuple() {
		Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		int count = 0;
		String query = "SELECT COUNT(*) FROM paging";
		
		try {
			conn = dataSource.getConnection();
			psmt = conn.prepareStatement(query);
			rs = psmt.executeQuery();
			
			if(rs.next()) {
				count = rs.getInt(1);
				System.out.println("list-count success");
			}			
		} catch (Exception e) {
			System.out.println("list-count fail");
			e.printStackTrace();
		} finally {
			try {
				if(rs != null) rs.close();
				if(psmt != null) psmt.close();
				if(conn != null) conn.close();
				System.out.println("< rs, psmt, conn close success>");
			} catch (Exception e) {
				System.out.println("< rs, psmt, conn close Fail>");
			}
		}
		
		return count;
	}
	//게시글 열람
	public Dto content(int no) {
		Dto dto = null;
		String query = "SELECT * FROM paging where no = ?";
		
		Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		
		try {
			conn = dataSource.getConnection();
			psmt = conn.prepareStatement(query);
			psmt.setInt(1, no);
			rs = psmt.executeQuery();
			
		if(rs.next()){
				int aNo = rs.getInt("no");
				String writer = rs.getString("writer");
				String title = rs.getString("title");
				String content = rs.getString("content");
				Timestamp date = rs.getTimestamp("date");
				
				dto = new Dto(aNo, writer, title, content, date);
				System.out.println("<content-data load success>");
			}
			
		} catch (Exception e) {
			System.out.println("<content-data load Fail>");
			e.printStackTrace();
		} finally {
			try {
				if(rs != null)
					rs.close();
				if(psmt != null)
					psmt.close();
				if(conn != null)
					conn.close();
			} catch (Exception e) {
				System.out.println("< rs, psmt, conn close Fail>");
				e.printStackTrace();
			}
		}
		
		return dto;
	}

}

 

List.jsp

<%@ 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>MVC Board</title>
</head>
<body>
	<table border="1">
		<tr>
			<td>번호</td>
			<td>이름</td>
			<td>제목</td>
			<td>날짜</td>
		</tr>
		<c:forEach items="${list }" var="dto">
			<tr>
				<td>${dto.no }</td>
				<td>${dto.writer }</td>
				<td><a href="content.do?no=${dto.no }">${dto.title }</a></td>
				<td>${dto.date }</td>
			</tr>
		</c:forEach>
			<tr>
				<td colspan="4" align="center">
					<!-- 페이징 부분 -->
					<c:forEach items="${pageList }" var="page">
						<a href="list.do?page=${page }">${page}</a>
					</c:forEach>
				</td>
			</tr>
			<tr>
				<td colspan="4" align="right"><a href="write_view.do">글작성</a></td>
			</tr>
	</table>
</body>
</html>

 

Content.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<table border="0">
		<form action="modify.do" method="post">
			<!-- <input type="hidden" name="bId" value="${content_view.bId }"> -->
			<tr>
				<td>번호</td>
				<td><input type="text" name="no" readonly="readonly" value="${content.no }"></td>
			</tr>
			<tr>
				<td>이름</td>
				<td><input type="text" name="name" szie="20" value="${content.writer }"></td>
			</tr> 
			<tr>
				<td>제목</td>
				<td><input type="text" name="title" szie="50" value="${content.title }"></td>
			</tr> 
			<tr>
				<td>내용</td>
				<td><textarea rows="10" cols="50" name="content">${content.content }</textarea></td>
			</tr> 
			<tr>
				<td colspan="2">
					<input type="submit" value="수정"> &nbsp; &nbsp; &nbsp;<a href="list.do?page=${courrentPage}">목록보기</a>
					&nbsp;&nbsp;&nbsp;<a href="delete.do?no=${content_view.bId }">삭제</a>
				</td>
			</tr>
		</form>
	</table>
</body>
</html>

 

반응형