JavaRush /Blog Java /Random-VI /Thêm ứng dụng khách vào bài viết - "Dự án Java từ A đến Z...
Roman Beekeeper
Mức độ

Thêm ứng dụng khách vào bài viết - "Dự án Java từ A đến Z"

Xuất bản trong nhóm
Xin chào tất cả mọi người, những người bạn thân yêu của tôi. Từng bước một, chúng tôi đang tiến gần hơn đến mục tiêu của mình - trở thành MVP cho dự án của chúng tôi - JavaRush Telegram Bot. Như tôi đã nói ở bài trước, chỉ còn lại 5 nhiệm vụ. Hôm nay chúng tôi sẽ đề cập đến hai trong số đó. "Dự án Java từ A đến Z": Thêm client vào bài viết - 1Tôi muốn nhắc lại rằng dự án sẽ không kết thúc ở đây. Tôi vẫn còn rất nhiều ý tưởng và tầm nhìn về cách dự án này sẽ phát triển, những điều mới nào có thể được thêm vào nó, những gì có thể làm tốt hơn. Trước MVP, chúng tôi sẽ làm một bài viết riêng về chủ đề tái cấu trúc - tức là về việc cải thiện chất lượng mã mà không thay đổi chức năng của nó. Vào thời điểm đó, toàn bộ dự án sẽ được hiển thị và sẽ rõ ràng những gì và ở đâu có thể được cải thiện. Trong trường hợp của chúng tôi, chúng tôi sẽ được bảo vệ tối đa khỏi việc phá vỡ chức năng vì nhiều bài kiểm tra đã được viết. Chúng tôi cũng sẽ viết một bản hồi tưởng về những gì chúng tôi muốn và những gì chúng tôi đạt được cuối cùng. Đây là một điều rất hữu ích: hãy xem mọi thứ được nhìn nhận chính xác như thế nào sáu tháng trước. Ít nhất điều này rất thú vị với tôi. Nếu bất kỳ ai muốn thử sức mình với tư cách là người thử nghiệm thủ công, hãy viết thư cho chúng tôi và chúng tôi sẽ cộng tác. Hãy cùng nhau làm cho dự án này tốt hơn! Vì vậy, đây là: hai nhiệm vụ được mô tả sáu tháng trước: JRTB-8JRTB-9 . Tôi bắt đầu xem xét những gì cần thực hiện cho những nhiệm vụ này và nhận ra rằng về mặt khởi chạy lệnh, mọi thứ đã sẵn sàng. Nó xảy ra...) Tại đây, bạn có thể xem StartCommand , phương thức thực thi :
@Override
public void execute(Update update) {
   String chatId = update.getMessage().getChatId().toString();

   telegramUserService.findByChatId(chatId).ifPresentOrElse(
           user -> {
               user.setActive(true);
               telegramUserService.save(user);
           },
           () -> {
               TelegramUser telegramUser = new TelegramUser();
               telegramUser.setActive(true);
               telegramUser.setChatId(chatId);
               telegramUserService.save(telegramUser);
           });

   sendBotMessageService.sendMessage(chatId, START_MESSAGE);
}
Logic hoạt động ở đây: nếu cơ sở dữ liệu của chúng tôi đã có một người dùng như vậy bằng chatId, chúng tôi chỉ cần đặt trường active = true cho anh ấy. Và nếu không có người dùng như vậy, chúng tôi sẽ tạo một người dùng mới. Tương tự với lệnh /stop trong StopCommand :
@Override
public void execute(Update update) {
   telegramUserService.findByChatId(update.getMessage().getChatId().toString())
           .ifPresent(it -> {
               it.setActive(false);
               telegramUserService.save(it);
           });
   sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), STOP_MESSAGE);
}
Có thể thấy khi gọi lệnh này chỉ có trường active = false được đặt cho người dùng. Và đó là tất cả: các đăng ký của anh ấy sẽ tồn tại và chờ đợi khi người dùng quyết định kích hoạt lại cuộc trò chuyện với bot. Và có vẻ như nhiệm vụ đã hoàn thành và có thể đóng lại. Nhưng nó không có ở đó. Nhiệm vụ quan trọng nhất là tạo thông báo về các bài viết mới trong mục đăng ký. Đây là nơi các nhiệm vụ này sẽ được cập nhật và hoàn thành đầy đủ. Tức là cho đến khi chúng tôi triển khai thông báo bài viết mới thì không thể đóng được. Vì vậy, hãy đảm nhiệm nhiệm vụ JRTB-4 - tạo kiểm tra 20 phút một lần và thông báo về các bài viết mới. Bạn! Bạn có muốn biết ngay khi nào mã mới cho dự án được phát hành không? Khi nào có bài viết mới? Tham gia kênh tg của tôi . Ở đó tôi thu thập các bài viết, suy nghĩ, sự phát triển nguồn mở của mình cùng nhau.

Chúng tôi triển khai JRTB-4

Những gì chúng ta cần làm như một phần của nhiệm vụ này:
  1. Tạo một công việc sẽ truy cập định kỳ tất cả các nhóm mà chúng tôi đăng ký trong cơ sở dữ liệu, sắp xếp các bài viết theo ngày xuất bản và kiểm tra xem ID của ấn phẩm cuối cùng có khớp với giá trị trong GroupSub hay không. Nếu nó không khớp thì bạn cần biết chính xác có bao nhiêu bài viết đã được xuất bản kể từ lần trước. Chúng tôi cập nhật Last_article_id trong GroupSub7 về trạng thái hiện tại.

  2. Khi chúng tôi tìm thấy danh sách các bài viết đã xuất bản, chúng tôi sẽ tìm tất cả người dùng HOẠT ĐỘNG của các nhóm này và gửi cho họ thông báo về các bài viết mới.

Để làm điều này, chúng tôi sẽ sử dụng một thứ như Spring Scheduler. Đây là một cơ chế trong Spring Framework, với nó, bạn có thể tạo các tác vụ sẽ được thực thi tại một thời điểm cụ thể. Cứ sau 15-20-40 phút, hoặc thứ Năm hàng tuần lúc 15:30 hoặc một số tùy chọn khác. Chúng còn được gọi là giấy truy tìm từ tiếng Anh - joba. Trong khi chúng tôi thực hiện nhiệm vụ này, tôi sẽ cố tình để lại một thiếu sót trong quá trình tìm kiếm các bài viết mới. Nó khá hiếm và chỉ xuất hiện trong tình huống tôi đã tự tay kiểm tra hoạt động của tác vụ này. Để làm được điều này bạn cần viết một client để tìm kiếm các bài báo. Để làm điều này, chúng tôi sẽ sử dụng API Swagger đã quen thuộc với chúng tôi . Có một bộ điều khiển sau. Chúng tôi chỉ quan tâm đến việc tìm kiếm một tập hợp các bài viết bằng các bộ lọc nhất định:
/api/1.0/rest/posts Nhận bài đăng theo bộ lọc
Chúng tôi sẽ làm việc với yêu cầu này. Chúng ta cần gì ở nó? Lấy danh sách các bài viết thuộc một nhóm cụ thể và chúng phải được sắp xếp theo ngày xuất bản. Bằng cách này, chúng tôi có thể lấy 15 bài viết gần đây nhất và kiểm tra xem các ấn phẩm mới đã được xuất bản dựa trên LastArticleId từ cơ sở dữ liệu của chúng tôi hay chưa. Nếu có, chúng tôi sẽ chuyển chúng để xử lý và gửi cho người dùng. Vì vậy chúng ta cần viết JavaRushPostClient .

Chúng tôi viết JavaRushPostClient

Ở đây, chúng tôi sẽ không cố gắng đáp ứng tất cả các yêu cầu đã được gửi cho chúng tôi trong API và sẽ chỉ tạo yêu cầu mà chúng tôi cần. Bằng cách này, chúng tôi đạt được hai mục tiêu cùng một lúc:
  1. Chúng tôi tăng tốc quá trình viết ứng dụng của chúng tôi.

  2. Chúng tôi giao công việc này cho những người muốn giúp đỡ cộng đồng của chúng tôi và quyết định thử sức mình với tư cách là một nhà phát triển. Tôi sẽ thực hiện các nhiệm vụ có thể hoàn thành sau MVP.

Vì vậy, hãy làm điều đó. Để truy vấn phần Mô hình trong Swagger UI, chúng tôi sẽ tạo các DTO sau:"Dự án Java từ A đến Z": Thêm client vào bài viết - 2

Thông tin người dùng cơ sở:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

import lombok.Data;

/**
* DTO, which represents base user information.
*/
@Data
public class BaseUserInfo {
   private String city;
   private String country;
   private String displayName;
   private Integer id;
   private String job;
   private String key;
   private Integer level;
   private String pictureUrl;
   private String position;
   private UserPublicStatus publicStatus;
   private String publicStatusMessage;
   private Integer rating;
   private Integer userId;
}

Ngôn ngữ:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents languages.
*/
public enum Language {
   UNKNOWN,
   ENGLISH,
   GERMAN,
   SPANISH,
   HINDI,
   FRENCH,
   PORTUGUESE,
   POLISH,
   BENGALI,
   PUNJABI,
   CHINESE,
   ITALIAN,
   INDONESIAN,
   MARATHI,
   TAMIL,
   TELUGU,
   JAPANESE,
   KOREAN,
   URDU,
   TAIWANESE,
   NETHERLANDS,
   RUSSIAN,
   UKRAINIAN
}

Thông tin lượt thích:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents like's information.
*/
public class LikesInfo {

   private Integer count;
   private LikeStatus status;
}

Trạng thái thích:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents like's status.
*/
public enum LikeStatus {

   UNKNOWN,
   LIKE,
   HOT,
   FOLLOW,
   FAVORITE,
   SOLUTION,
   HELPFUL,
   ARTICLE,
   OSCAR,
   DISLIKE,
   WRONG,
   SPAM,
   ABUSE,
   FOUL,
   TROLLING,
   OFFTOPIC,
   DUPLICATE,
   DIRTY,
   OUTDATED,
   BORING,
   UNCLEAR,
   HARD,
   EASY,
   FAKE,
   SHAM,
   AWFUL
}

Loại thư:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents post types.
*/
public enum PostType {
   UNKNOWN, USUAL, INNER_LINK, OUTER_LINK
}

Trạng thái công khai của người dùng:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents user public status.
*/
public enum UserPublicStatus {
   UNKNOWN,
   BEGINNER,
   ACTIVE,
   STRONG,
   GRADUATED,
   INTERNSHIP_IN_PROGRESS,
   INTERNSHIP_COMPLETED,
   RESUME_COMPLETED,
   LOOKING_FOR_JOB,
   HAVE_JOB;
}

VisibilityStatus:
package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents visibility status.
*/
public enum VisibilityStatus {
   UNKNOWN,
   RESTRICTED,
   PUBLIC,
   PROTECTED,
   PRIVATE,
   DISABLED,
   DELETED
}
Dựa trên tất cả các DTO này, hãy viết một lớp chính để nhận bài viết:

Thông tin bài viết:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

import lombok.Data;

/**
* DTO, which represents post information.
*/
@Data
public class PostInfo {

   private BaseUserInfo authorInfo;
   private Integer commentsCount;
   private String content;
   private Long createdTime;
   private String description;
   private GroupInfo groupInfo;
   private Integer id;
   private String key;
   private Language language;
   private LikesInfo likesInfo;
   private GroupInfo originalGroupInfo;
   private String pictureUrl;
   private Double rating;
   private Integer ratingCount;
   private String title;
   private PostType type;
   private Long updatedTime;
   private UserDiscussionInfo userDiscussionInfo;
   private Integer views;
   private VisibilityStatus visibilityStatus;

}
Bây giờ hãy tạo một giao diện để làm việc và cách triển khai nó. Chúng ta sẽ chỉ cần một phương pháp để làm việc với bài viết:

JavaRushPostClient:

package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;

import java.util.List;

/**
* Client for Javarush Open API corresponds to Posts.
*/
public interface JavaRushPostClient {

   /**
    * Find new posts since lastPostId in provided group.
    *
    * @param groupId provided group ID.
    * @param lastPostId provided last post ID.
    * @return the collection of the new {@link PostInfo}.
    */
   List<PostInfo> findNewPosts(Integer groupId, Integer lastPostId);
}
findNewPosts nhận hai đối số: ID nhóm và ID cuối cùng của bài viết mà bot đã đăng. Do đó, tất cả những bài viết được xuất bản muộn hơn bài viết có LastPostId sẽ được truyền đi . Và việc thực hiện nó:
package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;
import kong.unirest.GenericType;
import kong.unirest.Unirest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class JavaRushPostClientImpl implements JavaRushPostClient {

   private final String javarushApiPostPath;

   public JavaRushPostClientImpl(@Value("${javarush.api.path}") String javarushApi) {
       this.javarushApiPostPath = javarushApi + "/posts";
   }

   @Override
   public List<PostInfo> findNewPosts(Integer groupId, Integer lastPostId) {
       List<PostInfo> lastPostsByGroup = Unirest.get(javarushApiPostPath)
               .queryString("order", "NEW")
               .queryString("groupKid", groupId)
               .queryString("limit", 15)
               .asObject(new GenericType<List<PostInfo>>() {
               }).getBody();
       List<PostInfo> newPosts = new ArrayList<>();
       for (PostInfo post : lastPostsByGroup) {
           if (lastPostId.equals(post.getId())) {
               return newPosts;
           }
           newPosts.add(post);
       }
       return newPosts;
   }
}
Chúng tôi thêm một số bộ lọc vào yêu cầu:
  • order = NEW - để danh sách chứa những cái mới trước;
  • groupKid = groupId - chỉ tìm kiếm các nhóm nhất định;
  • limit = 15 — chúng tôi giới hạn số lượng bài viết cho mỗi yêu cầu. Tần suất của chúng tôi là 15-20 phút và chúng tôi hy vọng rằng trong thời gian này sẽ không viết QUÁ 15 (!)
Tiếp theo, khi chúng tôi tìm thấy các bài viết, chúng tôi xem qua danh sách và tìm kiếm những bài viết mới. Thuật toán rất đơn giản và trực quan. Nếu bạn muốn cải thiện nó, hãy viết). Hãy viết một bài kiểm tra đơn giản cho khách hàng này:
package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;

import static com.github.javarushcommunity.jrtb.javarushclient.JavaRushGroupClientTest.JAVARUSH_API_PATH;

@DisplayName("Integration-level testing for JavaRushPostClient")
class JavaRushPostClientTest {

   private final JavaRushPostClient postClient = new JavaRushPostClientImpl(JAVARUSH_API_PATH);

   @Test
   public void shouldProperlyGetNew15Posts() {
       //when
       List<PostInfo> newPosts = postClient.findNewPosts(30, 2935);

       //then
       Assertions.assertEquals(15, newPosts.size());
   }
}
Đây là một thử nghiệm rất đơn giản để kiểm tra xem có bất kỳ giao tiếp nào với khách hàng hay không. Anh ta tìm thấy 15 bài viết mới trong nhóm dự án Java, bởi vì tôi đưa cho anh ta ID của bài viết đầu tiên trong nhóm này, và đã có hơn 15 bài viết trong số đó... Đã có 22 bài trong số đó! Tôi thậm chí còn không nghĩ rằng sẽ có nhiều người như vậy. Làm thế nào tôi phát hiện ra một cách nhanh chóng? Bạn có nghĩ rằng anh ấy đã đi đếm chúng? Không) Tôi đã sử dụng một công cụ chuyển đổi và xem xét số lượng bài viết của một nhóm nhất định. Nhân tiện, bạn có thể xem xét những người khác theo cách này... Và có bao nhiêu bài viết trong nhóm RANDOM?... Bây giờ tôi sẽ nói cho bạn biết: có 1062 bài trong số đó! Số lượng nghiêm trọng.

Kết thúc phần đầu tiên

Ở đây chúng tôi đã thêm công việc với khách hàng theo bài viết. Chúng ta đã làm xong mọi việc rồi, lần này tôi nghĩ mọi thứ sẽ đơn giản và nhanh chóng. Trong bài viết tiếp theo chúng ta sẽ thêm Spring Scheduler và viết FindNewArticleService . Vâng, như thường lệ, thích - đăng ký - rung chuông , cho dự án của chúng tôi một ngôi sao , viết bình luận và đánh giá bài viết! Cảm ơn tất cả các bạn đã đọc - hẹn gặp lại!

Danh sách tất cả các tài liệu trong loạt bài này nằm ở đầu bài viết này.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION