JavaRush /จาวาบล็อก /Random-TH /การเพิ่มไคลเอนต์ให้กับบทความ - "โครงการ Java จาก A ถึง Z"...
Roman Beekeeper
ระดับ

การเพิ่มไคลเอนต์ให้กับบทความ - "โครงการ Java จาก A ถึง Z"

เผยแพร่ในกลุ่ม
สวัสดีทุกคนเพื่อนรักของฉัน ทีละขั้นตอนเราเข้าใกล้เป้าหมายของเรามากขึ้น - เพื่อเป็น MVP ของโครงการของเรา - JavaRush Telegram Bot อย่างที่ผมบอกไปแล้วในบทความที่แล้ว เหลือเพียง 5 งานเท่านั้น วันนี้เราจะกล่าวถึงสองเรื่อง "โครงการ Java จาก A ถึง Z": การเพิ่มไคลเอนต์ในบทความ - 1อยากจะย้ำว่าโครงการจะไม่จบแค่นี้ ฉันยังมีแนวคิดและวิสัยทัศน์มากมายว่าโครงการนี้ควรพัฒนาอย่างไร มีอะไรใหม่ๆ ที่สามารถเพิ่มเข้าไปได้ และอะไรจะทำได้ดีกว่านี้ ก่อน MVP เราจะจัดทำบทความแยกต่างหากในหัวข้อการรีแฟคเตอร์ - นั่นคือเกี่ยวกับการปรับปรุงคุณภาพของโค้ดโดยไม่ต้องเปลี่ยนฟังก์ชันการทำงาน เมื่อถึงเวลานั้น โครงการทั้งหมดจะสามารถมองเห็นได้ และจะชัดเจนว่าสิ่งใดและสิ่งใดที่สามารถปรับปรุงได้ ในกรณีของเรา เราจะได้รับการปกป้องสูงสุดจากการทำลายฟังก์ชันการทำงาน เนื่องจากมีการเขียนการทดสอบจำนวนมาก เราจะเขียนย้อนหลังเกี่ยวกับสิ่งที่เราต้องการและสิ่งที่เราได้ในที่สุด นี่เป็นสิ่งที่มีประโยชน์มาก เรามาดูกันว่าทุกอย่างถูกต้องแค่ไหนเมื่อหกเดือนที่แล้ว อย่างน้อยนี่ก็น่าสนใจมากสำหรับฉัน หากใครอยากลองใช้ตัวเองในฐานะผู้ทดสอบด้วยตนเอง เขียนถึงเรา แล้วเราจะร่วมมือกัน มาทำให้โครงการนี้ดีขึ้นด้วยกัน! ดังนั้นนี่คือ: สองงานที่อธิบายไว้เมื่อหกเดือนที่แล้ว: JRTB-8และJRTB-9 . ฉันเริ่มมองหาสิ่งที่จำเป็นต้องนำไปใช้สำหรับงานเหล่านี้ และตระหนักว่าในแง่ของการเรียกใช้คำสั่ง ทุกอย่างพร้อมแล้ว มันเกิดขึ้น...) ที่นี่คุณสามารถดูStartCommandวิธีการดำเนินการ :
@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);
}
ตรรกะใช้งานได้ที่นี่: หากฐานข้อมูลของเรามีผู้ใช้ดังกล่าวตาม chatId อยู่แล้ว เราก็เพียงตั้งค่าฟิลด์ active = true ให้กับเขา และหากไม่มีผู้ใช้ดังกล่าว เราจะสร้างผู้ใช้ใหม่ เช่นเดียวกับ คำสั่ง /stopใน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);
}
จะเห็นได้ว่าเมื่อเรียกใช้คำสั่งนี้เฉพาะฟิลด์ active = false เท่านั้นที่ถูกตั้งค่าสำหรับผู้ใช้ และนั่นคือทั้งหมด: การสมัครสมาชิกของเขาจะคงอยู่และรออยู่ในปีกเมื่อผู้ใช้ตัดสินใจเปิดใช้งานการแชทกับบอทอีกครั้ง และดูเหมือนว่างานจะเสร็จสิ้นแล้วและสามารถปิดได้ แต่มันไม่ได้อยู่ที่นั่น งานที่สำคัญที่สุดคือสร้างการแจ้งเตือนเกี่ยวกับบทความใหม่ในการสมัครสมาชิก นี่คือจุดที่งานเหล่านี้จะได้รับการอัปเดตและเสร็จสมบูรณ์อย่างสมบูรณ์ นั่นคือจนกว่าเราจะดำเนินการแจ้งเตือนบทความใหม่ ก็ไม่สามารถปิดได้ ดังนั้นมาจัดการงาน JRTB-4 กันเถอะ - สร้างเช็คทุก ๆ 20 นาทีและแจ้งเตือนเกี่ยวกับบทความใหม่ เพื่อน! คุณต้องการทราบทันทีเมื่อมีการเปิดตัวรหัสใหม่สำหรับโครงการหรือไม่? เมื่อไหร่จะมีบทความใหม่ออกมา? เข้าร่วมช่อง tg ของ ฉัน ที่นั่นฉันรวบรวมบทความ ความคิด และการพัฒนาโอเพ่นซอร์สของฉันไว้ด้วยกัน

เราใช้ JRTB-4

สิ่งที่เราต้องทำเพื่อเป็นส่วนหนึ่งของงานนี้:
  1. สร้างงานที่จะเยี่ยมชมกลุ่มทั้งหมดที่เราสมัครสมาชิกในฐานข้อมูลเป็นระยะๆ จัดเรียงบทความตามวันที่ตีพิมพ์ และตรวจสอบว่า ID ของการตีพิมพ์ครั้งล่าสุดตรงกับค่าใน GroupSub หรือไม่ หากไม่ตรงกัน ก็ต้องทำความเข้าใจให้แน่ชัดว่ามีบทความกี่บทความที่ได้รับการตีพิมพ์ตั้งแต่ครั้งล่าสุด เราอัปเดต Last_article_id ใน GroupSub7 เป็นสถานะปัจจุบัน

  2. เมื่อเราพบรายการบทความที่เผยแพร่ เราจะค้นหาผู้ใช้ที่ใช้งานอยู่ทั้งหมดของกลุ่มเหล่านี้ และส่งการแจ้งเตือนเกี่ยวกับบทความใหม่ให้พวกเขา

เพื่อที่จะทำสิ่งนี้ เราจะใช้สิ่งที่เรียกว่า Spring Scheduler นี่เป็นกลไกใน Spring Framework ซึ่งคุณสามารถสร้างงานที่จะดำเนินการในเวลาที่กำหนดได้ ทุก 15-20-40 นาที หรือทุกวันพฤหัสบดี เวลา 15:30 น. หรือทางเลือกอื่น พวกเขาเรียกอีกอย่างว่ากระดาษลอกลายจากภาษาอังกฤษ - joba ในขณะที่เรากำลังทำภารกิจนี้ ฉันจะจงใจทิ้งข้อบกพร่องไว้หนึ่งข้อเพื่อค้นหาบทความใหม่ มันค่อนข้างหายากและปรากฏเฉพาะในสถานการณ์ที่ฉันทดสอบการทำงานของงานนี้ด้วยตนเองเท่านั้น ในการดำเนินการนี้ คุณจะต้องเขียนไคลเอนต์เพื่อค้นหาบทความ ในการดำเนินการนี้ เราจะใช้ Swagger APIที่เราคุ้นเคยอยู่แล้ว มีผู้ควบคุมโพสต์ เราสนใจเฉพาะการค้นหาชุดบทความโดยใช้ตัวกรองบางตัวเท่านั้น:
/api/1.0/rest/posts รับโพสต์ตามตัวกรอง
เราจะดำเนินการตามคำขอนี้ เราต้องการอะไรในนั้น? รับรายชื่อบทความที่อยู่ในกลุ่มเฉพาะ และควรจัดเรียงตามวันที่ตีพิมพ์ วิธีนี้ทำให้เราสามารถนำ 15 บทความล่าสุดและตรวจสอบว่ามีการเผยแพร่สิ่งพิมพ์ใหม่ตามLastArticleIdจากฐานข้อมูลของเราหรือไม่ หากมีเราจะส่งต่อเพื่อประมวลผลและส่งไปยังผู้ใช้ ดังนั้นเราต้องเขียนJavaRushPostClient

เราเขียน JavaRushPostClient

ที่นี่เราจะไม่พยายามครอบคลุมคำขอทั้งหมดที่ส่งถึงเราใน API และจะสร้างเฉพาะคำขอที่เราต้องการเท่านั้น การทำเช่นนี้ทำให้เราบรรลุเป้าหมายสองประการพร้อมกัน:
  1. เราเร่งกระบวนการเขียนใบสมัครของเราให้เร็วขึ้น

  2. เราปล่อยให้งานนี้ตกเป็นของผู้ที่ต้องการช่วยเหลือชุมชนของเราและตัดสินใจลองใช้ตัวเองในฐานะนักพัฒนา ฉันจะทำงานนี้ให้สำเร็จได้หลังจาก MVP

เรามาทำกัน. หากต้องการสอบถาม ส่วน โมเดลในSwagger UIเราจะสร้าง DTO ต่อไปนี้:"โครงการ Java จาก A ถึง Z": การเพิ่มไคลเอนต์ในบทความ - 2

ข้อมูลผู้ใช้ฐาน:

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;
}

ภาษา:

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
}

ข้อมูลที่ชอบ:

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

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

   private Integer count;
   private LikeStatus status;
}

ชอบสถานะ:

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
}

ประเภทโพสต์:

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

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

สถานะสาธารณะของผู้ใช้:

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
}
จาก DTO ทั้งหมดนี้ มาเขียนชั้นเรียนหลักเพื่อรับบทความกัน:

ข้อมูลโพสต์:

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;

}
ตอนนี้เรามาสร้างอินเทอร์เฟซที่จะใช้งานและการใช้งานกันดีกว่า เราต้องการเพียงวิธีเดียวในการทำงานกับบทความ:

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รับสองอาร์กิวเมนต์: ID กลุ่มและ ID สุดท้ายของบทความที่บอทได้โพสต์ไว้แล้ว ดังนั้น บทความทั้งหมดที่เผยแพร่ช้ากว่าบทความที่มีLastPostId จะถูกส่งต่อ และการนำไปปฏิบัติ:
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;
   }
}
เราเพิ่มตัวกรองหลายรายการให้กับคำขอ:
  • order = NEW - เพื่อให้รายการมีรายการใหม่ก่อน
  • groupKid = groupId - ค้นหาเฉพาะบางกลุ่มเท่านั้น
  • ขีดจำกัด = 15 — เราจำกัดจำนวนบทความต่อคำขอ ความถี่ของเราคือ 15-20 นาที และเราคาดหวังว่าในช่วงเวลานี้จะเขียนได้ไม่เกิน 15 (!)
ต่อไป เมื่อเราพบบทความแล้ว เราจะดำเนินการตามรายการและค้นหาบทความใหม่ อัลกอริธึมนั้นเรียบง่ายและใช้งานง่าย หากคุณต้องการปรับปรุงเขียน) มาเขียนการทดสอบง่ายๆ สำหรับลูกค้ารายนี้:
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());
   }
}
นี่เป็นการทดสอบง่ายๆ ที่จะตรวจสอบว่ามีการสื่อสารกับลูกค้าเลยหรือไม่ เขาพบบทความใหม่ 15 บทความในกลุ่มโครงการ Java เพราะฉันให้ ID ของบทความแรกในกลุ่มนี้แก่เขาและมีมากกว่า 15 บทความแล้ว... มี 22 บทความแล้ว! ไม่คิดว่าจะมีเยอะขนาดนี้ ฉันรู้ได้อย่างไรอย่างรวดเร็ว? คุณคิดว่าเขาไปนับพวกเขาเหรอ? ไม่) ฉันใช้คำสวาทและดูจำนวนบทความของกลุ่มใดกลุ่มหนึ่ง ยังไงก็ตามคุณสามารถดูแบบนี้ในคนอื่น ๆ ได้... และมีบทความกี่บทความในกลุ่ม RANDOM?... ฉันจะบอกคุณตอนนี้: มี 1,062 บทความ! ปริมาณที่ร้ายแรง

จบภาคแรก

ที่นี่เราได้เพิ่มงานกับลูกค้าตามบทความ เราได้ทำทุกอย่างแล้ว คราวนี้ฉันคิดว่าทุกอย่างควรจะง่ายและรวดเร็ว ในบทความถัดไปเราจะเพิ่ม Spring Scheduler และเขียน FindNewArticleService ตามปกติเช่น - สมัครสมาชิก - กดกริ่งให้ ดาว โครงการของเราเขียนความคิดเห็นและให้คะแนนบทความ! ขอบคุณทุกท่านที่อ่าน - แล้วพบกันใหม่!

รายการเนื้อหาทั้งหมดในซีรีส์นี้อยู่ที่ตอนต้นของบทความนี้

ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION