스프링부트 게시판 페이지네이션/검색바 구현

https://rebornbb./entry/Springboot-%EA%B2%8C%EC%8B%9C%ED%8C%90%EB%94%B0%EB%9D%BC%ED%95%98 %EA%B8%B08-%EA%B2%80%EC%83%89-%EA%B8%B0%EB%8A%A5-%E2%9C%94%EC%A0%95%EB%A6% 에어컨

참고로 페이지네이션과 검색창을 구현했습니다.

페이징 관련 기능을 따로 모으기 위해 별도의 paginationService를 생성하고 바 길이도 서비스에 포함한다.

  • 페이징 서비스
@Service
public class PaginationService {
    private static final int BAR_LENGTH=5;
    
    public int getPaginationBarStartNumber(int currentPage, int totalPage){
        int startPage= Math.max(currentPage-BAR_LENGTH/2,1);
        return startPage;
    }

    public int getPaginationEndStartNumber(int startPage, int totalPage){
        int endPage=Math.min(startPage+BAR_LENGTH,totalPage);
        return endPage;
    }

}

  • 기사 컨트롤러
@GetMapping
public String SearchArticles(
        @PageableDefault(size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable,
        ModelMap map,
        String searchKeyword
){
    Page<Article> searchArticles =null;
    if(searchKeyword==null){ //검색을 하지 않았을 경우
        searchArticles=articleService.searchArticle(pageable);

    }else{
        searchArticles = articleService.searchArticles(searchKeyword,pageable);
    }

    int totalPage=searchArticles.getTotalPages();
    int nowPage = searchArticles.getPageable().getPageNumber() + 1; //pageable에서 넘어온 현재페이지를 가지고올수있다 * 0부터시작하니까 +1
    int startPage=paginationService.getPaginationBarStartNumber(nowPage,totalPage);
    int endPage=paginationService.getPaginationEndStartNumber(startPage,totalPage);

    map.addAttribute("searchArticles",searchArticles);
    map.addAttribute("nowPage", nowPage);
    map.addAttribute("startPage", startPage);
    map.addAttribute("endPage", endPage);


    return "articles/articleList";

}

  • 기사/articleList.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/default_layout}">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div layout:fragment="content">

    <main class="container">

        <table>
            <thead>
            <th>글 번호</th>
            <th>제목</th>
            <th>내용</th>
            </thead>
            <tbody>
            <tr th:each="article : ${searchArticles}">
                <td th:text="${article.id}"></td>

                <td>
                    <a th:href="http://duck-cow./m/@{/articles/{articleId}(articleId=${article.id})}"
                       th:text="${article.title}">제목
                    </a>
                </td>

                <td th:text="${article.content}"></td>

            </tr>
            <form th:action="@{/articles/form}" th:method="get">
                <button type="submit" th:text="'게시글 작성'"></button>
            </form>

            <form th:action="@{/logout}" method="post">
                <button type="submit" th:text="'로그아웃'"></button>
            </form>
            </tbody>
        </table>
    </main>

    <!--굳이 태그로 감쌀필요가없는 부분을 타임리프 문법을 사용할때 쓰는 문법 th:block-->
    <th:block th:each= "page : ${#numbers.sequence(startPage, endPage)}">
        <!--검색기능-4-->
        <a th:if="${page != nowPage}"
           th:href="@{/articles(page = ${page -1}, searchKeyword = ${param.searchKeyword})}"
           th:text="${page}">
        </a>

        <strong th:if="${page == nowPage}" th:text="${page}" style="color : red"></strong>
    </th:block>
    <form th:action="@{/articles}" method="get">
        <input type="text" name="searchKeyword">
        <button type="submit">검색</button>
    </form>
</div>

</body>
</html>