Hướng dẫn kỹ thuật phân trang hiển thị dữ liệu khi danh sách đối tượng dài.
Các nội dung chính
1. Thêm dependency Data vào file pom.xml để có hàm thư viện cho việc phân trang
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-commons</artifactId> <version>2.3.2.RELEASE</version> </dependency>
2. Ở bài này, ta xây dựng thêm tầng dịch vụ (service) dùng đề cung cấp dữ liệu cho Controller
- Định nghĩa Interface
package thomc.DisplayListObjectPagination.services; import org.springframework.stereotype.Service; import thomc.DisplayListObjectPagination.models.SinhVien; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @Service public interface SinhvienService { public Page<SinhVien> findPaginated(Pageable pageable); }
- Thực thi
package thomc.DisplayListObjectPagination.services; import org.springframework.stereotype.Service; import thomc.DisplayListObjectPagination.models.SinhVien; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @Service public class SinhVienServiceImpl implements SinhvienService { // Ta hard-code dữ liệu tại đây để tiện demo------ static List<SinhVien> dsSinhVien= new ArrayList<SinhVien>(); static { dsSinhVien.add(new SinhVien("0001", "Mai Cường Thọ")); dsSinhVien.add(new SinhVien("0002", "Trần Văn Long")); dsSinhVien.add(new SinhVien("0003", "Phạm Thị Hoa")); dsSinhVien.add(new SinhVien("0004", "Lê Hùng Cương")); dsSinhVien.add(new SinhVien("0005", "Phan Minh ANh")); dsSinhVien.add(new SinhVien("0006", "Lê Thị Hoa")); dsSinhVien.add(new SinhVien("0007", "Bụi Văn Cúc")); dsSinhVien.add(new SinhVien("0008", "Lê Hồng Phong")); dsSinhVien.add(new SinhVien("0009", "Lệ Chu Lai")); dsSinhVien.add(new SinhVien("0010", "Nguyễn Hùng Cường")); dsSinhVien.add(new SinhVien("0011", "Lê Bá Vương")); dsSinhVien.add(new SinhVien("0012", "Trần Thống Nhất")); } //----------hết phần hard-code dữ liệu --------------------- @Override public Page<SinhVien> findPaginated(Pageable pageable) { int pageSize = pageable.getPageSize(); int currentPage = pageable.getPageNumber(); int startItem = currentPage * pageSize; List<SinhVien> list; if (dsSinhVien.size() < startItem) { list = Collections.emptyList(); } else { int toIndex = Math.min(startItem + pageSize, dsSinhVien.size()); list = dsSinhVien.subList(startItem, toIndex); } Page<SinhVien> sinhvienPage = new PageImpl<SinhVien>(list, PageRequest.of(currentPage, pageSize), dsSinhVien.size()); return sinhvienPage; } }
3. Xây dựng Controller
package thomc.DisplayListObjectPagination.controllers; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import thomc.DisplayListObjectPagination.models.SinhVien; import thomc.DisplayListObjectPagination.services.SinhvienService; @Controller public class SinhVienController { @Autowired private SinhvienService svService; @GetMapping("/danhsachSV") public String listStudent(Model model, @RequestParam("page") Optional<Integer> page, @RequestParam("size") Optional<Integer> size) { final int currentPage = page.orElse(1); final int pageSize = size.orElse(5); Page<SinhVien> svPage = svService.findPaginated(PageRequest.of(currentPage - 1, pageSize)); model.addAttribute("dsSV", svPage); int totalPages = svPage.getTotalPages(); if (totalPages > 0) { List<Integer> pageNumbers = IntStream.rangeClosed(1, totalPages) .boxed() .collect(Collectors.toList()); model.addAttribute("pageNumbers", pageNumbers); } return "sinhvien_getAll_Paged"; } }
4. Trình bày tại View
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Danh sách sinh viên</title> </head> <body> <h1>Danh sách sinh viên</h1> <table border="1"> <thead> <tr> <th> Mã số sinh viên </th> <th> Họ và tên </th> </tr> </thead> <tbody> <tr th:each="sv: ${dsSV}"> <td th:text="${sv.maSoSV}" /> <td th:text="${sv.hoVaTen}" /> </tr> </tbody> </table> <div th:if="${dsSV.totalPages > 0}" th:each="pageNumber : ${pageNumbers}"> <a th:href="@{/danhsachSV(size=${dsSV.size}, page=${pageNumber})}" th:text=${pageNumber} th:class="${pageNumber==dsSV.number + 1} ? active"></a> </div> </body> </html>
Full mã nguồn: https://github.com/maicuongtho/SOT383-Web2CLC/tree/main/DisplayListObjectPagination