+3

(EzyPlatform) hướng dẫn phân trang lấy ra giới hạn số lượng bài viết trong dự án Web Blog

Phân trang trong EzyPlatform

Giới thiệu về PaginationModel và chức năng

1. PaginationModel:

Đầu tiên để hiểu về cách phân trang trong EzyPlatform chúng ta có Class PaginationModel với các thuộc tính sau:

image.png

Trong đó:

  • PageToken chứa các dữ liệu về nút nextprev với kiểu dữ liệu là String
  • Continuation có chứa 2 thuộc tính kiểm tra hasNexthasPrev với kiểu dữ liệu là Boolean nhằm kiểm tra xem điểm đầu và điểm cuối của dữ liệu

2. PaginationPostService

Trong bộ thư viện Ezyarticle chúng ta có các package service được cấu hình sẵn các phương thức hỗ trợ cho việc sử dụng dễ dàng hơn.

Ở đây khi làm việc với các bài Post ta có Class PaginationPostService sử dụng cho việc phân trang các bài Post:

image.png

ta có thể thấy Class này được extends tới Abstract Class CommonPaginationService đây là 1 class được sử dụng chung cho việc phân trang cho các Entity trong dự án của bạn, Class này nằm trong thư mục ezyplatform.service các bạn có thể tìm hiểu thêm tại đường dẫn:

package org.youngmonkeys.ezyplatform.service;

3. PaginationModelFetchers

Class này được sử dụng cho việc lấy dữ liệu phân trang, nó cung cấp các phương thức để lấy trang đầu tiên, trang cuối, trang tiếp theo và trang trước dựa trên các tham số như PaginationService, filter, nextPageToken, prevPageToken, thông tin là trang cuối (lastPage) và giới hạn số phần tử trên trang (limit).

  • Class này nằm trong package:
package org.youngmonkeys.ezyplatform.pagination;

image.png

4.CommonValidator

Class này sử dụng các phương thức để thực hiện các kiểm tra và xử lý lỗi cho các tham số đầu vào trong Web

  • Class này nằm trong package:
package org.youngmonkeys.ezyplatform.validator;

image.png

Cách hoạt động:

  • Class CommonValidator có các phương thức chủ yếu để kiểm tra tính hợp lệ của các đầu vào từ người dùng.
  • Nếu một điều kiện không được đáp ứng (ví dụ: pageSize không hợp lệ, kích thước Collection quá lớn, v.v.), nó sẽ ném ra một HttpBadRequestException với một thông báo lỗi phù hợp.
  • Sử dụng Collections.singletonMap để chỉ định lỗi cụ thể (ví dụ: "pageSize": "invalid").

Cách cài đặt

B1: đầu tiên chúng ta tạo ra Class Response chứa các thông tin Model cần gửi tới Font-End theo ví dụ sau:

image.png Trong Class này mình chỉ lấy ra các nội dung chính của bài viết như: tiêu đề, nội dung, hình ảnh..

B2: tiếp theo tại Class Service của bạn hãy thêm các thông tin sau:

@Service
@AllArgsConstructor
public class WebBlogPostControllerService {

    private final WebPostFilterFactory postFilterFactory;
    private final WebPaginationPostService paginationPostService;
    private final WebBlogPostModelDecorator blogPostModelDecorator;

    public PaginationModel<WebBlogPostResponse> getBlogPostPagination(
        String keyword,
        String nextPageToken,
        String prevPageToken,
        boolean lastPage,
        int limit
    ) {
        PaginationModel<PostModel> pagination = PaginationModelFetchers.getPaginationModel(
            this.paginationPostService,
            postFilterFactory.newDefaultPostFilterBuilder(keyword)
                .postStatus(PostStatus.PUBLISHED.toString())
                .build(),
            nextPageToken,
            prevPageToken,
            lastPage,
            limit
        );
        return blogPostModelDecorator.decorateBlogPostPagination(
            pagination
        );
    }

Chúng ta có thể thấy tại phương thức getBlogPostPagination được tạo ra với nhiệm vụ lấy danh sách Blog để phân trang dựa trên các tham số được truyền vào và sau khi có được pagination, phương thức này sẽ gửi dữ liệu tới Class Decorator để tiến hành bước tiếp theo

B3: sau khi có dữ liệu, chúng ta tiếp tục tạo ra Class Decorator với các thông tin như sau:

@EzySingleton
@AllArgsConstructor
public class WebBlogPostModelDecorator {

    private final WebMediaService mediaService;
    private final WebPostSlugService postSlugService;
    private final WebBlogModelToResponseConverter blogModelToResponseConverter;

    public PaginationModel<WebBlogPostResponse> decorateBlogPostPagination(
        PaginationModel<PostModel> pagination
    ) {
        List<PostModel> models = pagination.getItems();
        List<Long> postIds = newArrayList(
            models,
            PostModel::getId
        );
        Map<Long, String> slugByPostId = postSlugService.getLatestSlugMapByPostIds(
            postIds
        );
        Set<Long> imageIds = newHashSet(
            models,
            PostModel::getFeaturedImageId
        );
        Map<Long, MediaNameModel> imageById = mediaService
            .getMediaNameMapByIds(imageIds);
        return pagination.map(it ->
            blogModelToResponseConverter.toBlogPostResponse(
                it,
                slugByPostId.get(it.getId()),
                imageById.get(it.getFeaturedImageId())
            )
        );
    }
}

Class này có nhiệm vụ lấy ra các thông tin được gửi tới từ phương thức getBlogPostPagination trước đó và tiến hành tìm kiếm các thông tin mà phương thức blogModelToResponseConverter.toBlogPostResponse (được khởi tạo ở bước 1) yêu cầu

B4: Cuối cùng tại Controller chúng ta truyền tham số và gọi tới Service như sau:


@Controller
@AllArgsConstructor
public class HomeController {

    private final WebBlogPostControllerService blogPostControllerService;
    private final WebCommonValidator commonValidator;

    @DoGet("/")
    public View home(
        @RequestParam(value = "keyword") String keyword,
        @RequestParam(value = "nextPageToken") String nextPageToken,
        @RequestParam(value = "prevPageToken") String prevPageToken,
        @RequestParam(value = "lastPage") boolean lastPage,
        @RequestParam(value = "limit", defaultValue = "2") int limit
    ) {
        commonValidator.validatePageSize(limit);
        return View.builder()
            .template("home")
            .addVariable(
                "postPagination",
                blogPostControllerService.getBlogPostPagination(
                    keyword,
                    nextPageToken,
                    prevPageToken,
                    lastPage,
                    limit
                )
            )
            .addVariable(VIEW_VARIABLE_PAGE_TITLE, "home")
            .build();
    }

Tại controller, ta sử dụng CommonValidator sẽ kiểm tra xem các giá trị pageSize có hợp lệ hay không, nếu các giá trị hợp lệ chúng ta sẽ gửi Variable tới giao diện như sau:

.addVariable(
   "postPagination",
   blogPostControllerService.getBlogPostPagination(
       keyword,
       nextPageToken,
       prevPageToken,
       lastPage,
       limit
   )

Tóm tắt: Bài viết này giới thiệu và hướng dẫn cách phân trang bằng EzyPlatForm, bạn có thể tùy biến và sử dụng cho dự án của mình


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí