+2

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

Các nội dung:

  1. Lấy dữ liệu trong menu danh mục và hiển thị các danh mục con.
  2. Chuyển hướng và hiển thị chi tiết bài viết mà người dùng chọn.

Hiển thị dữ liệu cho menu danh mục

Bước 1: Tạo một Term Type có tên là danh mục và thêm các Term cho nó. Trong phần này Term Type là loại mục mà chúng ta tự định nghĩa, còn Term là các danh mục con của danh mục đó.

Bước 2: Tiếp theo, chúng ta cần viết mã để hiển thị danh mục và các danh mục con của nó trên phần header của trang web. Vì header là một thành phần (flagment) của trang web và nó sẽ hiển thị trên toàn bộ các trang mà Blog này có. Do đó, mỗi khi chuyển trang các dữ liệu của header đều được lấy ra để hiển thị. Như trong phần trước, chúng ta đã được biết đến một package có tên là view và bên trong nó chứa một lớp ViewDecorator, lớp này sẽ được sử dụng sau khi hệ thống trả về một View và trước khi mã html được tạo ra từ template. Do đó, mỗi lần chuyển trang dù là yêu cầu View nào thì nó cũng đều đi qua ViewDecorator (có thể hiểu rằng ViewDecorator sẽ bổ sung dữ liệu cho View - nhiệm vụ của nó tương tự như package controller.decorator mà chúng ta đã sử dụng ở phần trước). Chúng ta có thể thêm dữ liệu của phần header (hay bất kỳ dữ liệu khác như footer) thêm nó vào các View trước khi chúng được sử dụng để tạo ra bất kỳ một trang html nào.

Dưới đây là đoạn mã chúng ta sử dụng để thêm dữ liệu cho danh mục trong header:

package com.blog.essential.web.view;

import com.tvd12.ezyfox.bean.annotation.EzySingleton;
import com.tvd12.ezyhttp.server.core.view.View;
import lombok.AllArgsConstructor;
import org.youngmonkeys.ezyarticle.web.service.WebTermService;
import org.youngmonkeys.ezyplatform.web.view.WebViewDecorator;

import javax.servlet.http.HttpServletRequest;

@EzySingleton
@AllArgsConstructor
public class WebEssentialViewDecorator extends WebViewDecorator {

    private final WebTermService termService;

    @Override
    public void decorate(HttpServletRequest request, View view) {
        super.decorate(request, view);
        decorateMainMenu(view);
    }

    private void decorateMainMenu(View view) {
        view.setVariable(
            "categories",
            termService.getTermsInCategoryType()
        );
    }
}

Trong đoạn mã trên, chúng ta khai báo một TermService (lớp này đã được viết sẵn để thao tác với bảng Term có trong CSDL) sử dụng đối tượng này để thao tác với bảng Term có trong cơ sở dữ liệu. Đối tượng này sử dụng phương thức getTermsInCategoryType() để lấy ra tất cả các Term có trong Term Type category (nó trả về cho chúng ta một List các Term):

Lớp WebViewDecorator: lớp này có nhiệm vụ bổ sung dữ liệu của người dùng vào đối tượng View dựa trên thông tin có trong HttpServletRequest (HttpServletRequest là một đối tượng trong Java Servlet API đại diện cho yêu cầu HTTP từ client đến server. Đối tượng này chứa tất cả các thông tin liên quan đến yêu cầu HTTP, bao gồm: Headers, Parameters, Attributes, Session).

Phương thức decorate() ghi đè phương thức decorate() của lớp cha (WebViewDecorator). Nó gọi phương thức decorate() của lớp cha thực hiện một số công việc được định nghĩa trong (WebViewDecorator), sau đó nó gọi phương thức decorateMainMenu() để bổ sung thêm các dữ liệu cần thiết vào lớp View. Dữ liệu chúng ta muốn bổ sung ở đây là các dữ liệu của menu category

Bước 3: Thêm dữ liệu vào phần menu chúng ta muốn hiển thị category:

Đoạn mã html trên có sử dụng biểu thưc Thymeleaf th:block để khi câu lệnh if thực hiện bên trong nếu đúng thì block này sẽ được hiển thị còn nếu sai thì block này không được hiển thị. Sau đó, nó duyệt qua các category có trong danh sách categories lấy ra tên của category đó và slug (được sử dụng để hiển thị chi tiết cho danh mục - được giới thiệu ở phần sau của bài này).

Sau khi thực hiện xong, chúng ta sẽ được kết quả:


Hiển thị chi tiết của bài viết

Tóm tắt: Trong phần trước chúng ta đã thêm dữ liệu cho một bài viết trên Blog. Phần này chúng ta thiết lập để khi người dùng click vào bài viết thì người dùng sẽ được chuyển hướng tới trang chi tiết của bài viết.
Ý tưởng: Khi người dùng click và hình ảnh hoặc tiêu đề của bài viết để xem chi tiết của bài viết, lúc này thẻ <a> chứa một đường dẫn, đường dẫn này sẽ gọi đến một controller để xử lý và trả về cho người dùng giao diện chi tiết của bài viết mà người dùng vừa click.

Bước 1: Trong dự án, chúng ta thêm một class PostController để xử lý các yêu cầu liên quan đến bài viết. Chúng ta, sẽ sử dụng một lớp PostController đã được xây dựng sẵn, kế thừa lớp này để sử dụng.

package com.blog.essential.web.controller.view;

import com.tvd12.ezyhttp.server.core.annotation.Controller;
import org.youngmonkeys.ezyarticle.web.controller.service.WebCommentControllerService;
import org.youngmonkeys.ezyarticle.web.controller.service.WebPostControllerService;
import org.youngmonkeys.ezyarticle.web.controller.view.PostController;
import org.youngmonkeys.ezyarticle.web.service.WebEzyArticleSettingService;
import org.youngmonkeys.ezyarticle.web.service.WebTermService;
import org.youngmonkeys.ezyarticle.web.validator.WebTermValidator;
import org.youngmonkeys.ezyplatform.web.service.WebAdminService;
import org.youngmonkeys.ezyplatform.web.service.WebUserService;
import org.youngmonkeys.ezyplatform.web.validator.WebCommonValidator;

@Controller
public class WebEssentialPostController extends PostController {

    public WebEssentialPostController(
            WebAdminService adminService,
            WebUserService userService,
            WebTermService termService,
            WebEzyArticleSettingService settingService,
            WebPostControllerService postControllerService,
            WebCommentControllerService commentControllerService,
            WebCommonValidator commonValidator,
            WebTermValidator termValidator
    ) {
        super(
            adminService,
            userService,
            termService,
            settingService,
            postControllerService,
            commentControllerService,
            commonValidator,
            termValidator
        );
    }
}

Khi mở PostController lên chúng ta sẽ nhìn thấy đoạn code sau:

Đoạn code trên được xử lý khi có yêu cầu đến url: "/posts/{slug}".
Slug: được tạo ra khi tiêu đề của bài viết được tạo, tiêu đề có thể trùng nhau nhưng slug là luôn là duy nhất.

Bài viết sẽ được lấy ra theo slug và trước khi lấy ra slug sẽ được kiểm tra để kiểm tra xem nó có kiểu POST hay không. Cuối cùng phương thức build() sẽ tạo ra một đối tượng View chứa các thông tin của bài viết. (template("posts/details") chỉ định đoạn mã html sẽ được sử dụng để tạo ra, ở đây là details.html có trong thư mục posts) .

VÌ bài viết được lấy ra theo slug mà trong đoạn mã của phần trước chúng ta chưa thêm slug vào do đó cần phải thêm slug cho mainPost. Dưới đây là các đoạn mã được thay đổi:

Sử dụng "PostSlugService" (đã được viết sẵn) để lấy ra slug của post với postId được truyền vào:

Thêm slug vào "PostResponse":

Thêm slug vào "ModelToResponseConverter":

Sau khi đã thêm, chúng ta có thể thiết lập địa chỉ url cho thẻ <a>:

Lúc này, chúng ta đã có slug để hiển thị chi tiết bài viết. Tạo thêm một package posts và trong package này tạo một file html mới có tên là details.html (Vì trong PostController quy định đây là vị trí để nó để lấy mã html). Sau đó trong file này, chúng ta viết một số mã html để nhận các giá trị lấy được từ post.

Lúc này giao diện sẽ như sau:

Phần này gán dữ liệu cho danh mục và hiển trị trang chi tiết bài viết cho Blog


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í