- vừa được xem lúc

(EzyPlatform) Xây dựng phía Backend cho Blog - Phần 4

0 0 7

Người đăng: Nguyễn Nhật Anh

Theo Viblo Asia

Phân trang cho danh sách bài viết

Trong phần này, chúng ta phân trang cho danh sách các bài viết theo ngày xuất bản.

Ý tưởng: trong phần giao diện, thiết kế một nút bấm (loadmore), khi nhấn vào nút này load thêm các bài viết (nếu còn).

Thiết lập cho phía client

Thiết kế một nút bấm và xử lý sự kiện cho nút bấm này:

Dưới đây là hàm fetchPostList() sử dụng trong đoạn mã trên:

Hàm fetchPostList() được sử dụng để gửi yêu cầu đến API: /api/v1/posts để lấy danh sách bài viết. Nếu lastPostPageToken.next tồn tại nó sẽ được thêm vào queryString để yêu cầu trang tiếp theo của bài viết. Nếu ezyweb.lang tồn tại nó cũng được thêm vào queryString. Sau đó, sử dụng ajax để gửi yêu cầu get với các tham số đã xây dựng. limit=3 xác định số lượng bài viết muốn lấy ra trong mỗi lần nhấn.
Nếu yêu cầu thành công ('.done()'), dữ liệu trả về data sẽ được sử dụng để cập nhật lastPostPageToken. Thêm các bài viết mới vào #postListBody và kiểm tra xem còn bài viết hay không, nếu đã hết bài viết thì xóa đi nút next.
Nếu yêu cầu thất bại ('.fail()'), hàm ezyweb.processGetApiErrors(e) sẽ được gọi để xử lý lỗi.
Hàm buildPostListBodyHtml(posts) được sử dụng để xây dựng HTML cho danh sách bài viết từ data.items.

Hàm buildPostListItemHtml(post) sử dụng để lấy ra bài viết với dữ liệu tương ứng. Dưới đây là đoạn mã của hàm này:

Thiết lập cho phần Backend

  1. RequestParam
package com.blog.essential.web.controller.view; import com.blog.essential.web.controller.service.WebEssentialPostControllerService;
import com.blog.essential.web.response.WebLatestPostResponse;
import com.blog.essential.web.response.WebMostViewPostResponse;
import com.blog.essential.web.response.WebMostVotePostResponse;
import com.blog.essential.web.response.WebPostItemResponse;
import com.tvd12.ezyhttp.server.core.annotation.Controller;
import com.tvd12.ezyhttp.server.core.annotation.DoGet;
import com.tvd12.ezyhttp.server.core.annotation.RequestParam;
import com.tvd12.ezyhttp.server.core.view.View;
import lombok.AllArgsConstructor;
import org.youngmonkeys.ezyarticle.web.validator.WebTermValidator;
import org.youngmonkeys.ezyplatform.model.PaginationModel;
import org.youngmonkeys.ezyplatform.web.validator.WebCommonValidator; import java.util.List; import static org.youngmonkeys.ezyplatform.constant.CommonConstants.VIEW_VARIABLE_PAGE_TITLE; @Controller
@AllArgsConstructor
public class HomeController { private final WebEssentialPostControllerService essentialPostControllerService; private final WebCommonValidator commonValidator; private final WebTermValidator termValidator; @DoGet("/") public View home( @RequestParam("author") String authorUuid, @RequestParam("term") String termSlug, @RequestParam("keyword") String keyword, @RequestParam("nextPageToken") String nextPageToken, @RequestParam("prevPageToken") String prevPageToken, @RequestParam("lastPage") boolean lastPage, @RequestParam(value = "limit", defaultValue = "1") int limit ) { this.commonValidator.validatePageSize(limit); this.commonValidator.validateSearchUuid(authorUuid); this.commonValidator.validateSearchKeyword(keyword); this.termValidator.validateSearchTerm(termSlug); WebPostItemResponse mainPost = essentialPostControllerService.getMainPostOrNull(); List<WebPostItemResponse> extraPosts = essentialPostControllerService.getExtraPosts(); List<WebMostViewPostResponse> mostViewPosts = essentialPostControllerService .getMostViewPosts(); List<WebMostVotePostResponse> mostVotePosts = essentialPostControllerService .getMostVotePosts(); PaginationModel<WebLatestPostResponse> latestPostPagination = essentialPostControllerService .getPostPagination( authorUuid, termSlug, keyword, nextPageToken, prevPageToken, lastPage, limit ); return View.builder() .template("home") //--> Hàm .addVariable("mainPost", mainPost) .addVariable("extraPosts", extraPosts) .addVariable("mostViewPosts", mostViewPosts) .addVariable("mostVotePosts", mostVotePosts) .addVariable("latestPostPagination", latestPostPagination) .addVariable(VIEW_VARIABLE_PAGE_TITLE, "home") .build(); }
}

Ý nghĩa của các param sử dụng trong bài:

  • author: tên tác giả - được sử dụng để lấy ra các bài viết của tác giả được chỉ định.
  • term: lấy ra các bài viết theo term.
  • keyword: dùng để lọc bài viết theo một số điều kiện cụ thể (author, slug, status, type).
  • nextPageToken: một token lưu trữ vị trí bắt đầu cho lần lấy tiếp theo.
  • prevPageToken: một tonken lưu trữ vị trí bắt đầu của lần lấy trước đó.
  • lastPage: dùng để xác định trang hiện tại có phải là trang cuối cùng hay không.
  • limit: là số bài viết mặc định ban đầu khi load trang.

VD về nextPageToken: {"sortOrder":"PRIORITY_DESC_ID_DESC","value":{"priority":0,"id":12}}

Đoạn mã trên được sử dụng khi trang home được gọi đến và các bài viết mặc định được lấy ra. Còn trong đoạn mã dưới, nó được gọi khi nhấn vào nút loadmore để lấy dữ liệu cho các bài viết tiếp theo:

package com.blog.essential.web.controller.api; import com.blog.essential.web.controller.service.WebEssentialPostControllerService;
import com.blog.essential.web.response.WebLatestPostResponse;
import com.blog.essential.web.response.WebPostVoteResponse;
import com.tvd12.ezyhttp.server.core.annotation.*;
import lombok.AllArgsConstructor;
import org.youngmonkeys.ezyarticle.sdk.entity.PostType;
import org.youngmonkeys.ezyarticle.sdk.model.PostModel;
import org.youngmonkeys.ezyarticle.web.service.WebPostService;
import org.youngmonkeys.ezyarticle.web.validator.WebPostValidator;
import org.youngmonkeys.ezyarticle.web.validator.WebTermValidator;
import org.youngmonkeys.ezyplatform.model.PaginationModel;
import org.youngmonkeys.ezyplatform.web.validator.WebCommonValidator; import javax.servlet.http.HttpServletRequest;
import java.math.BigInteger; import static org.youngmonkeys.ezyplatform.util.HttpRequests.getLanguage; @Api
@Controller("/api/v1")
@AllArgsConstructor
public class WebEssentialApiPostController { private final WebPostService postService; private final WebEssentialPostControllerService essentialPostControllerService; private final WebCommonValidator commonValidator; private final WebPostValidator postValidator; private final WebTermValidator termValidator; @DoGet("/posts") public PaginationModel<WebLatestPostResponse> postsGet( HttpServletRequest request, @RequestParam("author") String authorUuid, @RequestParam("term") String termSlug, @RequestParam("keyword") String keyword, @RequestParam("nextPageToken") String nextPageToken, @RequestParam("prevPageToken") String prevPageToken, @RequestParam("lastPage") boolean lastPage, @RequestParam(value = "limit", defaultValue = "3") int limit ) { this.commonValidator.validatePageSize(limit); this.commonValidator.validateSearchUuid(authorUuid); this.commonValidator.validateSearchKeyword(keyword); this.termValidator.validateSearchTerm(termSlug); return this.essentialPostControllerService .getPostPagination( authorUuid, termSlug, keyword, nextPageToken, prevPageToken, lastPage, limit ); } @DoPost("/posts/{slug}/vote") public WebPostVoteResponse postsSlugVoteUpPost( HttpServletRequest request, @PathVariable String slug ) { PostModel post = postValidator .validatePublishedPostSlugWithTypeAndLanguage( slug, PostType.POST.toString(), getLanguage(request) ); BigInteger totalVote = postService.increaseVoteCount( post.getId() ); return new WebPostVoteResponse(totalVote); }
} 
  1. Phân trang bài viết

Từ các param nhận được, truyền vào và sử dụng các param. Xác định các tiêu chí để lấy ra các bài viết.

Trong PostControllerService, viết một hàm để xử lý các param này:

Hàm trên sử dụng một bộ lọc - lọc ra các tiêu chí của bài viết:

Truyền vào hàm getPostPagination() thứ hai với các tham số tương ứng:

Lấy ra PaginationModel chứa các bài viết theo tiêu chí lọc ở trên (các bài viết được lưu trong items của PaginationModel).

Đưa các qua decorator để lấy hết các thông tin cần thiết cho bài viết (items).

Đưa qua Converter, lọc ra các thông tin cần thiết cho items.


  1. Dữ liệu được sử dụng

Sau khi lấy ra được dữ liệu, hàm done() trong ajax được gọi:

Data ở đây tương ứng với PaginationModel<WebLatestPostResponse>, data.items sẽ lấy ra dữ liệu của các bài viết, lấy dữ liệu đó xây dựng cho các bài viết tiếp theo.

Phần này hướng dẫn phân trang cho danh sách các bài viết.

Bình luận

Bài viết tương tự

- vừa được xem lúc

EzyPlatform - Giới thiệu về nền tảng Lập trình từ người Việt

Giới thiệu về Ezyplatform - Nền tảng lập trình từ người Việt. Ezyplatform là gì.

0 0 19

- vừa được xem lúc

EzyPlatform - Tạo blog dễ dàng với EzyBlog - Không cần code hay thiết kế

Giới thiệu. Bạn muốn tạo một trang blog nhưng không muốn đối mặt với sự phức tạp của việc lập trình hay thiết kế web? Đừng lo, EzyPlatform là giải pháp cho bạn.

0 0 20

- vừa được xem lúc

EzyPlatform - Cách tích hợp đăng nhập nhanh chóng với EzyLogin - Không cần code hay thiết kế

Giới thiệu. Bạn muốn tạo một trang web với tính năng đăng nhập, đăng ký cho người dùng, nhưng không muốn phải đối mặt với sự phức tạp của việc lập trình hay thiết kế giao diện đăng nhập? Đừng lo, EzyL

0 0 18

- vừa được xem lúc

Tích hợp Đăng nhập với Google vào Ứng dụng Web với EzyLogin - Phần 2

Giới thiệu. Trong phần 1, chúng ta đã khám phá cách tích hợp tính năng đăng nhập và đăng ký cơ bản vào ứng dụng web của bạn bằng EzyLogin.

0 0 29

- vừa được xem lúc

Tích hợp Đăng nhập với Facebook vào Ứng dụng Web với EzyLogin - Phần 3

Giới thiệu. Trong phần 2 chúng ta đã tìm hiểu cách tích hợp tính năng đăng nhập và đăng ký bằng Google với EzyLogin.

0 0 24

- vừa được xem lúc

Tạo dự án EzyPlatform

Khởi tạo project. Bước 1: Cài đặt SDK và giải nén. . Bước 3: Thêm %EZYPLATFORM_SDK%in vào biến path.

0 0 13