일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 인증코드로 비밀번호 변경 구현
- jquery
- js
- 대분류/중분류/소분류
- 세션
- Spring MVC
- jsp 프로젝트
- MySQL
- 교보문고 따라하기
- 오라클
- Level 1
- 일단_해보는거야
- Oracle
- 자바
- 로그인과 장바구니 구현
- 고객센터 구현
- jsp
- Spring
- MVC
- Sts
- SESSION
- 이메일로 인증코드 전송 구현
- 스프링
- ajax
- jakarta.mail
- 프로그래머스
- json
- 다중 카테고리 구현
- java
- 코딩
감 잃지말고 개발하기
[JSP][MVC][MySQL] Select 박스 옵션에 따른 페이징 처리 구현하기 #3. 로직 구현(마지막) 본문
도서 목록 페이지에서 <Select> 박스 옵션에 따른 페이징 처리 로직을 기록하고자 한다.
저번 포스팅에서는 기본적인 페이징 처리 로직을 구현해 보았다.
기본적인 페이징 처리 이해를 바탕으로 이번 포스팅에서 <select> 박스 옵션에 따른 페이징 처리 로직을 정리해 봄으로써 구현을 완성해 보도록 하겠다.
서버 딴 로직은 이전 포스팅에서 정리한 코드에서 살짝씩 수정 및 보충할 것이니
자세한 설명은 이전 포스팅을 참고해 주길 바란다.
♠ 해당 구현의 로직 흐름이 궁금하면 아래 포스팅을 참고하세요 ♠
2023.05.27 - [JSP/MVC] - [JSP][MVC][MySQL] Select 박스 옵션에 따른 페이징 처리 구현하기 #1. 기본 설정
[JSP][MVC][MySQL] Select 박스 옵션에 따른 페이징 처리 구현하기 #1. 기본 설정
도서 목록 페이지에서 박스 옵션에 따른 페이징 처리 로직을 총 2개의 포스팅에 걸쳐 기록하고자 한다. 이번 포스팅에서는 구현 흐름과 필요한 테이블 및 클래스를 정리해 보도록 하겠다. 목표
persimmon-ary-stepbystep.tistory.com
목표
♠ <select> 박스 옵션에 따른 페이징 처리를 구현할 수 있다.
로직 코드 및 실행화면
1. 도서 목록 페이지
1-1. ▼ 도서 목록 페이지
1-2. ▼ <select> 옵션 HTML
두 개의 <select> 박스의 클래스명은 "sort-select"로 동일하다.
두 개의 <select> 박스 중 어느 옵션을 선택하던지 간에 두 개의 옵션 값이 모두 URL의 파라미터로 설정되어 서버에 요청되게 할 것이다.
이전 포스팅에서 설명했듯이,
전체 / 국내 도서 / 외국 도서는 book 테이블의 "b_main_catgy" 칼럼, 즉 대분류 값을 의미한다.
전체를 선택하면 0이, 국내 도서를 선택하면 1이, 외국 도서를 선택하면 2가 URL 파라미터로 설정된다.
<div class="sorting">
<select class="sort-select">
<option value="s0">전체</option>
<option value="s1">국내 도서</option>
<option value="s2">외국 도서</option>
</select>
</div>
<div class="sorting mr-auto">
<select class="sort-select">
<option value="l9">9개씩 보기</option>
<option value="l15">15개씩 보기</option>
<option value="l21">21개씩 보기</option>
</select>
</div>
1-3. ▼ <select> 옵션 클릭 JS 코드
☞ $('.sort-select').on('change', function() { });
어느 <select> 박스를 선택하던지 간에 'change' 이벤트를 호출해 두 개의 옵션 값을 모두 URL의 파라미터로 설정하도록 할 것이다.
☞ $('.sort-select').not(this);
클래스명이 "sort-select"인 요소 중, 현재 사용자가 선택한 <select> 박스가 아닌 다른 <select> 박스를 찾는다.
<script type="text/javascript">
$(document).ready(function() {
/* select박스 옵션 선택 */
$('.sort-select').on('change', function() {
var selectedOption = $(this).val(); // 선택된 값 가져오기
var otherSelect = $('.sort-select').not(this); // 현재 선택 상자와 다른 선택 상자 찾기
// 선택된 값 출력하기
console.log('현재 선택 상자: ' + selectedOption);
console.log('다른 선택 상자: ' + otherSelect.val());
});
});
</script>
원래 위의 코드로 작성하면, 콘솔 창에 <select> 박스의 옵션 값이 정상적으로 출력되어야 한다.
위의 코드로 잘 출력되면 위의 코드를 사용하면 된다.
하지만 나의 경우, 가져온 부트스트랩 템플렛의 내부 JS 코드 때문인지 해당 코드가 잘 동작하지 않았다.
HTML 코드를 살펴보니 아래처럼 되어 있었다.
알고 보니, <select> 박스가 display:none이 되고 <ul> 태그가 대신 나타난 것이었다.
게다가 내가 선택한 옵션은 클래스 명에 "selected"가 추가되어 나타나고 있었다.
때문에 나는 class="list"의 class="option selected"으로 접근해서 값을 가져왔다.
▼ 수정한 <select> 옵션 클릭 JS 코드
☞ $('.list').children('li.option.selected').each(function() { ));
class명이 list인 요소의 자식 중, <li> 태그의 클래스명이 option selected인 요소를 가져와서 루프를 돈다.
☞ $(this).data('value');
위 이미지를 보면, 내가 가져오고자 하는 <li> 태그의 값이 속성 data-value에 들어있다.
data() 함수는 속성 data-value의 값을 가져오거나 설정할 때 사용할 수 있다.
☞ switch(selectedOption.slice(0,1))
사용자가 선택한 옵션 값의 첫 단어로 대분류 값인지, 출력 도서 개수 값인지를 구분한다.
대분류 값이면 파라미터 sort의 값으로, 출력 도서 개수 값이면 파라미터 limit의 값에 넣어서 서버에 전송한다.
<script type="text/javascript">
$(document).ready(function() {
/* select박스 옵션 선택 */
$('.sort-select').on('change', function() {
var sortValue = '';
var limitValue = '';
// 선택한 선택 상자와 다른 선택 상자의 선택된 값 가져오기
$('.list').children('li.option.selected').each(function() {
selectedValue = $(this).data('value');
console.log('상자: ' + selectedValue);
switch(selectedValue.slice(0,1)) {
case 's':
sortValue = selectedValue.slice(1);
break;
default:
limitValue = selectedValue.slice(1);
break;
}
});
// 선택된 값 출력하기
console.log('sortValue: ' + sortValue);
console.log('limitValue: ' + limitValue);
// 서버로 전송
location.href='/bookList.ok?sort='+sortValue+'&limit='+limitValue;
});
});
</script>
값이 잘 출력되는지 확인해 보자.
아래는 첫 번째 <select> 박스에서 "국내 도서"를 택했을 때의 콘솔 결과이다.
▼ 출력 확인
sortValue엔 국내 도서의 숫자 1이, limitValue엔 9가 출력되었음을 확인할 수 있다.
다음은 두 번째 <select> 박스에서 "15개씩 보기"를 택했을 때의 결과를 보자.
▼ 출력 확인
sortValue엔 국내 도서의 숫자 1이, limitValue엔 15가 출력되었음을 확인할 수 있다.
2. 컨트롤러(BookFrontController.java)
이전 포스팅 참고
3. Action 클래스(BookListAction.java)
이전 포스팅의 Action 클래스를 아래처럼 수정한다.
☞ 요청 URL 파라미터 관련 설정
<select> 옵션이 들어간 URL은 http://localhost:.../bookList.ok?sort=0&limit=9 와 같이 2개의 파라미터를 가진다.
각각의 파라미터는 아래와 같은 정보를 지닌다.
- 파라미터 sort : 가져올 도서 대분류(전체 / 국내도서 / 외국도서)
- 파라미터 limit : 한 화면에 출력할 도서 개수
이에 따라 위 2개의 파라미터와 함께 페이지 번호를 저장할 변수를 초기화해준다.
- int page : 파라미터 page 값을 저장(기본값 1)
- int limit : 파라미터 limit 값을 저장(기본값 9)
- int b_main_catgy : 파라미터 sort 값을 저장(기본값 0)
☞ service.getListCount(b_main_catgy);
기존의 getListCount() 메서드에 파라미터 b_main_catgy를 넘겨주어 대분류 값에 따른 도서 개수를 가져오도록 한다.
☞ service.getBookList(page, b_main_catgy, limit);
기존의 getBookList(int page, int limit) 메서드에 파라미터 b_main_catgy를 넘겨주어 대분류 값에 따른 도서를 가져오도록 한다.
☞ req.setAttribute("sort", b_main_catgy);
req.setAttribute("limit", limit);
HttpServletRequest 객체에 대분류 값과 출력될 도서 개수를 속성으로 설정한다. 포워딩을 했을 때 bookList.jsp 페이지에서 사용할 수 있도록 하기 위함이다.
package action;
import java.util.ArrayList;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import svc.BookListService;
import vo.ActionForward;
import vo.Book;
import vo.PageInfo;
/** 책 상품 목록보기 요청을 처리하는 Action 클래스*/
public class BookListAction implements Action {
@Override
public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
/* 필요 변수 초기화 */
int page = 1;
int limit = 9;
int b_main_catgy = 0;
/* URL 파라미터 설정 */
if(req.getParameter("page") != null) {
page = Integer.parseInt(req.getParameter("page"));
}
if(req.getParameter("sort") != null) {
b_main_catgy = Integer.parseInt(req.getParameter("sort"));
}
if(req.getParameter("limit") != null) {
limit = Integer.parseInt(req.getParameter("limit"));
}
System.out.println("b_main_catgy : "+b_main_catgy);
System.out.println("limit : "+limit);
/* DB 처리
* 1. DB에 저장된 총 책 개수 GET
* 2. 지정한 페이지에 출력될 책 목록을 GET */
BookListService service = new BookListService();
int listCount = service.getListCount(b_main_catgy);
ArrayList<Book> bookList = service.getBookList(page, b_main_catgy, limit);
/* 페이징 처리
* 1. 총 페이지 수(나머지가 있는 경우에만 올림처리) 계산
* 2. 페이징 부분에 출력되는 페이지 번호 중 첫 번째 페이지 번호(1, 11, 21 등) 계산
* 3. 페이징 부분에 출력되는 페이지 번호 중 마지막 페이지 번호(10, 20, 30 등) 계산 */
int maxPage = listCount / limit + (listCount % limit == 0 ? 0 : 1);
int startPage = (((int)((double)page / 10 + 0.9)) - 1) * 10 + 1;
int endPage = startPage + 10 - 1;
// 계산된 endPage 값을 존재하는 페이지의 마지막 페이지 번호(maxPage)로 지정
if(endPage > maxPage) endPage = maxPage;
/* 페이징에 관한 정보를 저장할 PageInfo 객체 생성 */
PageInfo pageInfo = new PageInfo();
pageInfo.setEndPage(endPage);
pageInfo.setListCount(listCount);
pageInfo.setMaxPage(maxPage);
pageInfo.setPage(page);
pageInfo.setStartPage(startPage);
/* 포워딩할 때 가져갈 정보 저장
* 1. 책 상품 목록 정보를 속성으로 공유
* 2. pageInfo 객체를 request 영역에 속성 값으로 공유
* 3. 도서 분류 값을 속성으로 공유
* 4. limit 값을 속성으로 공유
* .ok -> .jsp : Forward
* */
req.setAttribute("bookList", bookList);
req.setAttribute("pageInfo", pageInfo);
req.setAttribute("sort", b_main_catgy);
req.setAttribute("limit", limit);
ActionForward forward = new ActionForward();
forward.setPath("/book/bookList.jsp");
forward.setRedirect(false);
return forward;
}
}
4. Service 클래스(BookListService.java)
기존 메서드에 파라미터 b_main_catgy를 받아 bookDAO 객체의 각 메서드에 파라미터로 다시 던져준다.
package svc;
import java.sql.Connection;
import java.util.ArrayList;
import dao.BookDAO;
import vo.Book;
import static db.JdbcUtil.*;
/** 책 상품 목록보기 요청을 처리하는 비즈니스 로직을 구현하는 Service 클래스*/
public class BookListService {
public int getListCount(int b_main_catgy) {
int listCount = 0;
/* DB 처리 */
Connection conn = getConnection();
BookDAO boardDAO = BookDAO.getInstance();
boardDAO.setConnection(conn);
listCount = boardDAO.selectListCount(b_main_catgy);
close(conn);
return listCount;
}
public ArrayList<Book> getBookList(int page, int b_main_catgy, int limit) throws Exception{
/* DB 처리 */
BookDAO bookDAO = BookDAO.getInstance();
Connection conn = getConnection();
bookDAO.setConnection(conn);
ArrayList<Book> bookList = bookDAO.selectBookList(page, b_main_catgy, limit);
close(conn);
return bookList;
}
}
5. DAO 클래스(BookDAO.java)
이전 포스팅의 DAO 클래스 메서드를 아래와 같이 수정한다.
☞ if(b_main_catgy != 0) sql += " WHERE b_main_catgy = " + b_main_catgy;
book 테이블의 b_main_catgy 칼럼에는 1(국내 도서)과 2(외국 도서)의 값만 저장된다.
하지만 파라미터 b_main_catgy의 값에는 0(전체)이 올 수 있기 때문에 그에 대한 처리를 해준다.
파라미터 b_main_catgy의 값이 0이 아닌 경우에만 쿼리문에 WHERE 절이 추가되도록 한다.
/** 전체 책 개수 구하는 메서드 */
public int selectListCount(int b_main_catgy) {
int listCount = 0;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "SELECT COUNT(*) FROM jspbookshop.book";
if(b_main_catgy != 0) sql += " WHERE b_main_catgy = " + b_main_catgy;
try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
if(rs.next()) {
listCount = rs.getInt(1);
}
} catch (Exception e) {
System.out.println(" selectListCount ERROR : "+e);
} finally {
close(rs);
close(pstmt);
}
return listCount;
}
/** 해당 페이지에 출력될 책 상품 목록을 반환하는 메서드 */
public ArrayList<Book> selectBookList(int page, int b_main_catgy, int limit) {
PreparedStatement pstmt = null;
ResultSet rs = null;
ArrayList<Book> bookList = null;
String book_sql = null;
switch (b_main_catgy) {
case 1:
case 2:
book_sql = "SELECT * "
+ "FROM jspbookshop.book "
+ "WHERE b_main_catgy = " + b_main_catgy + " "
+ "ORDER BY b_publish_date DESC "
+ "LIMIT ?, ? ";
break;
default:
book_sql = "SELECT * "
+ "FROM jspbookshop.book "
+ "ORDER BY b_publish_date DESC "
+ "LIMIT ?, ? ";
break;
}
System.out.println("sql: "+book_sql);
int startrow = (page-1)*limit;
try {
pstmt = conn.prepareStatement(book_sql);
pstmt.setInt(1, startrow);
pstmt.setInt(2, limit);
rs = pstmt.executeQuery();
if (rs.next()) {
bookList = new ArrayList<>();
do {
bookList.add(new Book(
rs.getInt("b_id"),
rs.getString("b_name"),
rs.getString("b_writer"),
rs.getString("b_translator"),
rs.getString("b_publisher"),
rs.getString("b_catgy"),
rs.getInt("b_price"),
rs.getString("b_image"),
rs.getInt("b_page"),
rs.getString("b_publish_date"),
rs.getString("b_content"),
rs.getInt("b_readcount")));
} while (rs.next());
}
} catch (Exception e) {
System.out.println(" B.DAO : selectBookList ERROR : "+e);
} finally {
close(rs);
close(pstmt);
}
return bookList;
}
6. bookList.jsp
<select> 박스와 페이징 처리 부분을 아래와 같이 수정한다.
포워딩했을 때 request 내장 객체의 ${sort} 및 ${limit} 값에 따라 <option>이 selected 되도록 해주고,페이징 처리 <a> 태그의 속성 href 값에 파라미터 sort와 limit가 들어가도록 다시 설정해 준다.
<div class="filter-bar d-flex flex-wrap align-items-center">
<div class="sorting">
<select class="sort-select">
<option value="s0">전체</option>
<option value="s1" <c:if test='${sort eq 1 }'>selected="selected"</c:if>>국내 도서</option>
<option value="s2" <c:if test='${sort eq 2 }'>selected="selected"</c:if>>외국 도서</option>
</select>
</div>
<div class="sorting mr-auto">
<select class="sort-select">
<option value="l9">9개씩 보기</option>
<option value="l15"<c:if test='${limit eq 15 }'>selected="selected"</c:if>>15개씩 보기</option>
<option value="l21"<c:if test='${limit eq 21 }'>selected="selected"</c:if>>21개씩 보기</option>
</select>
</div>
<c:if test="${pageInfo.listCount != null }">
<div class="pagination">
<!-- 이전 화살표 -->
<c:if test="${pageInfo.page > 10 }">
<a href="/bookList.ok?page=${pageInfo.page-1 }&sort=${sort}&limit=${limit}" class="prev-arrow"><i class="fa fa-long-arrow-left pt-3" aria-hidden="true"></i></a>
</c:if>
<c:forEach var="a" end="${pageInfo.endPage }" step="1" begin="${pageInfo.startPage }">
<c:if test="${a == pageInfo.page}">
<a>${a }</a>
</c:if>
<c:if test="${a != pageInfo.page}">
<a href="/bookList.ok?page=${a }&sort=${sort}&limit=${limit}">${a }</a>
</c:if>
</c:forEach>
<!-- 다음 화살표 -->
<c:if test="${pageInfo.endPage < pageInfo.maxPage }">
<a href="/bookList.ok?page=${pageInfo.endPage+1 }&sort=${sort}&limit=${limit}" class="next-arrow">
<i class="fa fa-long-arrow-right pt-3" aria-hidden="true"></i>
</a>
</c:if>
</div>
</c:if>
</div>
7. 브라우저 결과
각각의 경우에 따른 대분류 값과 표시될 도서 개수, 그리고 쿼리문을 서버 딴 콘솔창에서 확인해 보자.
경우 1. 도서 목록 페이지 최초 요청
요청 URL은 http://localhost:8090/bookList.ok이다.
경우 2. 첫 번째 <select> 옵션 선택
요청 URL은 http://localhost:8090/bookList.ok?sort=2&limit=9이다.
외국 도서가 9개씩 출력되고 있는 걸 확인할 수 있다.
경우 3. 두 번째 <select> 옵션 선택
요청 URL은 http://localhost:8090/bookList.ok?sort=2&limit=15이다.
외국 도서가 15개씩 출력되고 있는 걸 확인할 수 있다.
경우 4. 두 번째 페이지 클릭
요청 URL은 http://localhost:8090/bookList.ok?page=2&sort=2&limit=15이다.
두 번째 페이지에서 외국 도서가 15개씩 출력되고 있는 걸 확인할 수 있다.
(마지막 페이지라 14개만 출력되었다.)
이렇게 <select> 박스 옵션에 따른 페이징 처리를 구현한 로직이 모두 완성되었다.
페이징 처리 끝.
'JSP > MVC' 카테고리의 다른 글
[JSP][MVC][MySQL] 도서 등록 페이지 카테고리 구현하기 #3. 클라 딴 구현(마지막) (0) | 2023.06.01 |
---|---|
[JSP][MVC][MySQL] 도서 등록 페이지 카테고리 구현하기 #2. 서버 딴 구현 (0) | 2023.05.31 |
[JSP][MVC][MySQL] 도서 등록 페이지 카테고리 구현하기 #1. 기본 세팅 (0) | 2023.05.31 |
[JSP][MVC][MySQL] Select 박스 옵션에 따른 페이징 처리 구현하기 #2. 로직 구현 (0) | 2023.05.27 |
[JSP][MVC][MySQL] Select 박스 옵션에 따른 페이징 처리 구현하기 #1. 기본 설정 (0) | 2023.05.27 |
[JSP][MVC][Session] 세션 및 로그인 도서 장바구니 구현하기 #7. 장바구니 수량 변경하기 (2탄) (0) | 2023.05.24 |