ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ Spring Boot + JPA + Thymeleaf ] 검색 기능 구현
    Spring Boot 2021. 3. 4. 21:46

    검색기능 

    - 게시판 리스트에서 검색어를 입력 후 버튼을 누르면 제목과 내용에 해당 검색어가 포함되는 리스트들을 출력해주는 기능을 구현 할 것이다.

     


     

    1. Controller

    - BoardController.java

    @Controller
    @RequestMapping("/board")
    public class BoardController {
    
        @Autowired
        private BoardRepository boardRepository;
    
        @Autowired
        private BoardValidator boardValidator;
    
        // 리스트 출력
        @GetMapping("/list")
        public String list(Model model, @PageableDefault(size = 2) Pageable pageable,
                           @RequestParam(required = false, defaultValue = "") String searchText){
            //Page<Board> boards = boardRepository.findAll(pageable);
            Page<Board> boards = boardRepository.findByTitleContainingOrContentContaining(searchText,searchText,pageable);
    
            int startPage = Math.max(1,boards.getPageable().getPageNumber() - 4);
            int endPage = Math.min(boards.getTotalPages(),boards.getPageable().getPageNumber() + 4);
    
            model.addAttribute("startPage",startPage);
            model.addAttribute("endPage",endPage);
            model.addAttribute("boards", boards);
            return "board/list";
        }

    우선 검색기능 구현을 위해 검색어 값을 넘겨받아야 하므로 searchText인자를 추가해주었다. 그리고 해당 값이 없을 경우도 있기떄문에 에러방지를 위해 @RequestParam의 required값을 false로 두었다. 그리고 제목과 내용에서 해당 검색어가 포함되는 리스트를 출력하기 위해서 findByTitleContainingOrContentContaining메서드를 사용해 주었다.

     

    이제 findByTitleContainingOrContentContaining을 repository에 선언해주면 된다.

     

    2. Repository

    - BoardRepository.java

    package com.example.myhome.repository;
    
    import com.example.myhome.model.Board;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    import java.util.List;
    
    public interface BoardRepository extends JpaRepository<Board, Long> {
    
        List<Board> findByTitle(String title);
        List<Board> findByTitleOrContent(String title,String content);
    
        Page<Board> findByTitleContainingOrContentContaining(String title, String content, Pageable pageable);
    }

    3. View

    - list.html

    <!doctype html>
    <html xmlns:th="http://www.thymelef.org">
    <head th:replace="fragments/common :: head('게시판')">
    </head>
    <body>
    <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:replace="fragments/common :: menu('list')">
    </nav>
    
    <div class="container">
        <h2>게시판</h2>
        <div>총 건수 : <span th:text="${boards.totalElements}"></span></div>
        <form class="row g-3 align-items-center d-flex justify-content-end" method="GET" th:action="@{/board/list}">
            <div class="col-auto">
                <label for="searchText" class="col-form-label">검색</label>
            </div>
            <div class="col-auto">
                <input type="text" id="searchText" class="form-control" name="searchText" th:value="${param.searchText}">
            </div>
            <div class="col-auto">
                <button type="submit" class="btn btn-light">검색</button>
            </div>
    
        </form>
        <table class="table">
            <thead>
            <tr>
                <th scope="col">번호</th>
                <th scope="col">제목</th>
    
            </tr>
            </thead>
            <tbody>
            <tr th:each="board : ${boards}">
                <th th:text="${board.id}">1</th>
                <td><a th:text="${board.title}" th:href="@{/board/form(id=${board.id})}" >Mark</a></td>
    
            </tr>
            </tbody>
        </table>
        <nav aria-label="Page navigation example">
            <ul class="pagination">
                <li class="page-item" th:classappend="${1 == boards.pageable.pageNumber+1} ? 'disabled' ">
                    <a class="page-link" href="#" th:href="@{/board/list(page=${boards.pageable.pageNumber-1},searchText=${param.searchText})}">Previous</a>
                </li>
                <li class="page-item" th:classappend="${i == boards.pageable.pageNumber+1} ? 'disabled' " th:each="i : ${#numbers.sequence(startPage,endPage)}">
                    <a class="page-link" href="#" th:text="${i}" th:href="@{/board/list(page=${i-1},searchText=${param.searchText})}">1</a>
                </li>
                <li class="page-item" th:classappend="${boards.totalPages == boards.pageable.pageNumber+1} ? 'disabled' ">
                    <a class="page-link" href="#" th:href="@{/board/list(page=${boards.pageable.pageNumber+1},searchText=${param.searchText})}">Next</a>
                </li>
            </ul>
        </nav>
        <div class="text-right">
            <a type="button" class="btn btn-primary" th:href="@{/board/form}">글쓰기</a>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
    </body>
    </html>

    검색 버튼을 누를경우 위의 코드들이 실행되면서 결과에 맞는 값을 뿌려준다. 그런데 페이지가 새로고침되면서 입력했던 검색어 글자가 초기화되는것을 볼 수 있다. 그것을 방지하기 위해서 파라미터로 표현되있는 검색어값을 input의 value값에 넣어주는 코드를 추가해줄것이다.

     

    th:value="${param.searchText}"

     

    해당 코드를 넣어주면 된다.

     

    아, 그리고 페이징 이동시에도 해당값이 초기화되기때문에 페이징 url넘길때 searchText값도 같이 넘겨주어야 한다.


    실행화면

     

     

     

Designed by Tistory.