728x90
나의 첫 포스팅 😮💨
프젝하다가 페이징 처리 해야하는데
복습 안했더니 기억안나서
부랴부랴 되짚어보는 페이징 부분 정리 !
우선 컨트롤러를 작성하기 전에 페이징에 필요한 정보를 정리해보자.
페이징(Paging)|페지네이션(Pagination)
- [c]페이지 당 표시할 게시글의 수(경우에 따라 다르지만 클라이언트에게 맡기는 경우가 대부분이지만 우린 상수로 빼놓을것) : 10
- [P]요청한 페이지 번호 > Assert >=1
- [t]전체 게시글의 개수 > DB
- [n]이동 가능한 최소 페이지(<<) : 1
- [x] 이동 가능한 최대 페이지(>>): t%c !=0 ? (t/c)+1 :t/c || (t-1)/c+1 > 후자가 성능상 유리함
- [s] 표시 시작 페이지: p/10 == 0 ? 1 : 10 * (p/10)+1 || ((p-1)/10)*10+1 > 후자가 성능상 유리함
- [e] 표시 끝 페이지: Math.min(s+9,x) || s+9 >x ? x: (s+9) >> 항상! 이동가능한 페이지 이하이기때문. 13을 요청했을때 생각해보자
= LIMIT n OFFSET (p-1)*n
<Controller>
@RequestMapping(value = "list",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ModelAndView getList(@RequestParam(value = "bid") String bid, //boardId
@RequestParam(value = "page", required = false,
defaultValue = "1") Integer page,
@RequestParam(value = "criterion", required = false) String criterion, // 검색기준
@RequestParam(value = "keyword", required = false) String keyword)//검색어 {
page = Math.max(1, page);
ModelAndView modelAndView = new ModelAndView("bbs/list");
BoardEntity board = this.bbsService.getBoard(bid);
modelAndView.addObject("board", board);
int totalCount; //pagination 하려고 가져온 것
if ( board != null) {
totalCount = this.bbsService.getArticleCount(board, criterion, keyword);
PagingModel paging = new PagingModel(totalCount, page);
modelAndView.addObject("paging", paging);
ArticleReadVo[] articles = this.bbsService.getArticles(board, paging,criterion,keyword);
modelAndView.addObject("articles", articles);
}
return modelAndView;
}
<Service>
// 게시물을 가져오는 서비스
public ArticleReadVo[] getArticles(BoardEntity board, PagingModel paging,String criterion,String keyword) {
// 매개변수로 갖는 게시판의 종류,검색기준, 검색어, 페이지당 표시할 게시글의 개수 ,
return this.bbsMapper.selectArticlesByBoardId(
board.getId(), //게시판의 종류
criterion, // 검색기준
keyword, // 검색어
paging.countPerPage, // 페이지당 표시할 게시글의 개수
(paging.requestPage-1)*paging.countPerPage);
//(요청한 페이지 번호-1)*페이지당 표시할 게시글의 개수
}
//검색 서비스
public int getArticleCount (BoardEntity board, String criterion, String keyword) {
return this.bbsMapper.selectArticleCountByBoardId(board.getId(),criterion,keyword);
}
<IMapper>
ArticleReadVo[] selectArticlesByBoardId(@Param(value = "boardId") String boardId,
@Param(value = "criterion") String criterion,
@Param(value = "keyword") String keyword,
@Param(value = "limit") int limit,
@Param(value = "offset") int offset);
int selectArticleCountByBoardId(@Param(value = "boardId") String boardId,
@Param(value = "criterion") String criterion,
@Param(value = "keyword") String keyword);
<Mapper>
<select id="selectArticlesByBoardId"
resultType="dev.yhpark.studymemberbbs.vos.bbs.ArticleReadVo">
SELECT `article`.`index` AS `index`,
`article`.`user_email` AS `userEmail`,
`article`.`board_id` AS `boardId`,
`article`.`title` AS `title`,
`article`.`view` AS `view`,
`article`.`written_on` AS `writtenOn`,
`article`.`modified_on` AS `modifiedOn`,
COUNT(`comment`.`index`) AS `commentCount`,
`user`.`nickname` AS `userNickName`
FROM `study_bbs`.`articles` AS `article`
LEFT JOIN `study_member`.`users` AS `user` ON `article`.`user_email` = `user`.`email`
LEFT JOIN `study_bbs`.`comments` AS `comment` ON `comment`.`article_index` = `article`.`index`
WHERE BINARY `article`.`board_id` = #{boardId}
<if test="criterion != null and criterion.equals('title')">
AND REPLACE(`article`.`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="criterion !=null and criterion.equals('all')">
AND (REPLACE(`article`.`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
OR REPLACE(`article`.`content`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%'))
</if>
<if test="criterion !=null and criterion.equals('nickName')">
AND BINARY `user`.`nickname` = #{keyword}
</if>
GROUP BY `article`.`index`
ORDER BY `article`.`index` DESC
LIMIT #{limit} OFFSET #{offset};
</select>
<select id="selectArticleCountByBoardId"
resultType="int">
SELECT COUNT(0)
FROM `study_bbs`.`articles` AS `article`
<if test="criterion !=null and criterion.equals('nickName')">
LEFT JOIN `study_member`.`users` AS `user` ON `article`.`user_email` = `user`.`email`
</if>
WHERE `board_id` = #{boardId}
<if test="criterion != null and criterion.equals('title')">
AND REPLACE(`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
</if>
<if test="criterion !=null and criterion.equals('all')">
AND (REPLACE(`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
OR REPLACE(`content`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%'))
</if>
<if test="criterion !=null and criterion.equals('nickName')">
AND BINARY `user`.`nickname` = #{keyword}
</if>
</select>
<HTML>
<div class="page-container"
th:with="urlBuilder = ${T(org.springframework.web.servlet.support.
ServletUriComponentsBuilder).fromCurrentRequest()}">
<a th:if="${paging.requestPage > 1}"
th:href="@{${urlBuilder.replaceQueryParam('page',paging.minPage).build().toUriString()}}"
class="page">
<i class="fa-solid fa-angles-left"></i>
</a>
<a th:if="${paging.requestPage > 1}"
th:href="@{${urlBuilder.replaceQueryParam('page',(paging.requestPage)-1).build().toUriString()}}"
class="page">
<i class="fa-solid fa-angle-left"></i>
</a>
<a class="page"
th:each="page:${#numbers.sequence(paging.startPage,paging.endPage)}"
th:class="${'page '+(page == paging.requestPage?'selected':'')}"
th:text="${page}"
th:href="@{${urlBuilder.replaceQueryParam('page',page).build().toUriString()}}"></a>
<a href="#" class="page"
th:if="${paging.requestPage < paging.maxPage}"
th:href="@{${urlBuilder.replaceQueryParam('page',(paging.requestPage)+1).build().toUriString()}}">
<i class="fa-solid fa-angle-right"></i>
</a>
<a th:if="${paging.requestPage < paging.maxPage}"
th:href="@{${urlBuilder.replaceQueryParam('page',paging.maxPage).build().toUriString()}}"
class="page">
<i class="fa-solid fa-angles-right"></i>
</a>
</div>
728x90
'Spring' 카테고리의 다른 글
[Spring] Spring 이란 ? (37) | 2023.10.29 |
---|---|
[오류] 유효한 문자는 RFC 7230 and RFC 3986에서 정의 오류 (0) | 2023.06.17 |
[SpringBoot] email Auth: 이메일 인증 구현하기 (1) | 2023.02.22 |
[SpringBoot] 회원가입 구현하기 (0) | 2023.02.14 |
[SprinBoot] @ResponseBody 어노테이션 (0) | 2022.12.27 |