+5

(EzyPlatform) Sử dụng hình ảnh của bài post nổi bật để làm hình ảnh Slider trong dự án xây dựng Blog

Trong trang web, sử dụng các slider là 1 cách để làm nổi bật các blog hot, dưới đây là 1 cách bạn có thể sử dụng khi muốn lấy hình ảnh từ bài viết để làm hình ảnh cho banner như vậy

Cách cài đặt

B1: Tạo Interface WebBlogPostRepository với các thông tin sau:

@EzyRepository
public interface WebBlogPostRepository extends EzyDatabaseRepository<Long, Post> {
    
    //đặt câu lệnh tìm kiếm SQL bằng id post và sắp xếp theo thứ tự priority giảm dần
    @EzyQuery(
        "SELECT e FROM Post e WHERE e.id IN ?0 ORDER BY e.priority DESC"
    )
    List<Post> findByIdInOrderByPriorityDesc(List<Long> ids);
}

B2: Tiếp theo tạo Class WebBlogPostService với các thông tin sau

@Service
@AllArgsConstructor
public class WebBlogPostService {

    private final WebBlogPostRepository blogPostRepository;
    private final WebPostTermRepository postTermRepository;
    private final WebTermRepository termRepository;
    private final WebEzyArticleEntityToModelConverter ezyArticleEntityToModelConverter;

    public List<PostModel> getHighlightPostsOrderByPriorityDesc() {
    
        //tìm kiếm term dựa trên type và slug
        Term term = termRepository.findByTermTypeAndSlug(
            TermType.CATEGORY.toString(),
            TERM_HIGHLIGHT
        );
        
        // sau khi có term sẽ tiến hành tìm kiếm danh sách id các bài viết chứa termId trùng khớp 
        List<Long> postIds = Collections.emptyList();
        if (term != null) {
            postIds = newArrayList(
                postTermRepository
                    .findListByField("termId", term.getId()),
                PostTerm::getPostId
            );
        }
        
        // nếu không tìm thấy postId nào thì return
        if (postIds.isEmpty()) {
            return Collections.emptyList();
        }
        
        // nếu danh sách postIds khác null thì tiến hành tìm kiếm các bài post theo id và Priority giảm dần
        return newArrayList(
            blogPostRepository.findByIdInOrderByPriorityDesc(postIds),
            ezyArticleEntityToModelConverter::toModel
        );
    }
}

Trong đó:

  • Class WebEzyArticleEntityToModelConverter dùng để tạo thông tin Modal cho tất cả các đối tượng như: Post, Comment,…
  • TERM_HIGHTLIGHT được khai báo tại package [project]-sdk và được định nghĩa là Constants

B3: Tạo Class WebHightlightPostResonse chứa thông tin sau:

@Getter
@Builder
public class WebHighlightPostResponse {
    private final String postSlug;
    private final MediaNameModel image;
}

B4: Tạo class Converter để Conver giữ liệu từ response

@EzySingleton
public class WebBlogModelToResponseConverter {

    public WebHighlightPostResponse toHighlightPostResponse(
        String slug,
        MediaNameModel image
    ) {
        return WebHighlightPostResponse.builder()
            .postSlug(slug)
            .image(image)
            .build();
    }
}

B5: trong package controller tạo package decorator chứa Class WebBlogPostModelDecorator

@EzySingleton
@AllArgsConstructor
public class WebBlogPostModelDecorator {

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

    public List<WebHighlightPostResponse> decorate(List<PostModel> models) {
        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 newArrayList(
            models,
            it -> blogModelToResponseConverter.toHighlightPostResponse(
                slugByPostId.get(it.getId()),
                imageById.get(it.getFeaturedImageId())
            )
        );
    }
}

B6: trong package controller tạo ra package service chứa Class WebBlogPostControllerService

@Service
@AllArgsConstructor
public class WebBlogPostControllerService {

    private final WebBlogPostService blogPostService;
    private final WebBlogPostModelDecorator blogPostModelDecorator;

    public List<WebHighlightPostResponse> getHighlightPostsOrderByPriorityDesc() {
        List<PostModel> posts = blogPostService
                .getHighlightPostsOrderByPriorityDesc();
        return blogPostModelDecorator.decorate(posts);
    }
}

B7: sau khi hoàn thành các bước trên tại HomeController thêm:

.addVariable(
"highlightPosts",
    blogPostControllerService.getHighlightPostsOrderByPriorityDesc()
)

như sau:

@Controller
@AllArgsConstructor
public class HomeController {
    private final WebBlogMenuItemService blogMenuItemService;
    private final WebBlogPostControllerService blogPostControllerService;

    @DoGet("/")
    public View home() {
        return View.builder()
            .template("home")
            .addVariable(
                "mainMenuItems",
                blogMenuItemService.getMaiMenuItems()
            )
            .addVariable(
            "highlightPosts",
                blogPostControllerService.getHighlightPostsOrderByPriorityDesc()
            )
            .addVariable(VIEW_VARIABLE_PAGE_TITLE, "home")
            .build();
    }
}

Thêm thông tin phía Admin

B1: Tạo term với tên là hightlight

B2: Sau đó tạo 1 bài posts và thêm các thông tin như hình ảnh, chọn term highlight và đặt tên

B3: Cuối cùng chúng ta chỉ cần lấy ra thông tin trên giao diện bằng thymleaf

<div th:each="highlightPost : ${highlightPosts}" class="carousel-item active">
    <img th:src="${highlightPost.image != null ? highlightPost.image.getUrlOrNull() : '' }"
     class="d-block w-100" alt="..." style="height: 500px">
</div>

cách thức hoạt động

1. Đầu tiên khi HomeController được khởi chạy sẽ gọi tới hàm getHighlightPostsOrderByPriorityDesc() thuộc Class WebBlogPostControllerService để tiến hành tìm kiếm dữ liệu.

2. Sau đó WebBlogPostControllerService sẽ gọi tới Class WebBlogPostService tìm kiếm danh sách các bài post thông qua hàm getHighlightPostsOrderByPriorityDesc()

3. Hàm getHighlightPostsOrderByPriorityDesc() sẽ tìm kiếm theo các bước:

  • Tìm kiếm term dựa trên type và slug (ở đây sẽ là type = CATEGORY, và slug = “highlight“)
  • Sau khi tìm kiếm term sẽ tiến hành lấy danh sách Post id dựa trên termIds thông qua PostTermRepository
  • khi đã có postId bước cuối cùng sẽ tìm kiếm bài post dựa trên id và sắp xếp theo Priority giảm dần và sử dụng ezyArticleEntityToModelConverter để converter dữ liệu về dạng Model
  • sau khi đã hoàn thành dữ liệu sẽ được trả về cho WebBlogPostControllerService

4. Khi dữ liệu được trả về getHighlightPostsOrderByPriorityDesc() sẽ gửi dữ liệu tới WebBlogPostModelDecorator

  • khi Decorator nhận dữ liệu sẽ bắt đầu lấy ra danh sách postIds thông qua models
  • sau đó tiếp tục lấy ra slug từ postIds bằng phương thức postSlugService.getLatestSlugMapByPostIds(postIds);
  • tương tự sẽ tiến hành lấy danh sách id hình ảnh từ models Set<Long> imageIds = newHashSet(models,PostModel::getFeaturedImageId);
  • tiếp theo lấy thông tin hình ảnh qua id mediaService.getMediaNameMapByIds(imageIds);
  • cuối cùng dữ liệu trước khi được trả về sẽ được converter thông qua phương thức: blogModelToResponseConverter.toHighlightPostResponse
return newArrayList(
    models,
    it -> blogModelToResponseConverter.toHighlightPostResponse(
        slugByPostId.get(it.getId()),
        imageById.get(it.getFeaturedImageId())
    )
);

5. sau cùng dữ liệu sẽ được truyền vào biến highLightPosts trước đó và gửi tới giao diện


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í