JavaRush /Java blogi /Random-UZ /Maqolalarga mijoz qo'shish - "A dan Zgacha Java loyihasi"...

Maqolalarga mijoz qo'shish - "A dan Zgacha Java loyihasi"

Guruhda nashr etilgan
Hammaga salom aziz do'stlarim. Biz bosqichma-bosqich maqsadimizga – loyihamizning MVP – JavaRush Telegram Botiga aylanishga yaqinlashyapmiz. Oxirgi maqolada aytganimdek, atigi 5 ta vazifa qoldi. Bugun biz ulardan ikkitasini ko'rib chiqamiz. "A dan Zgacha Java loyihasi": Maqolalarga mijoz qo'shish - 1Yana takror aytmoqchimanki, loyiha shu bilan tugamaydi. Ushbu loyiha qanday rivojlanishi kerakligi, unga qanday yangi narsalarni qo'shish mumkinligi va nimani yaxshiroq qilish mumkinligi haqida menda hali ham ko'plab g'oyalar va qarashlar mavjud. MVP dan oldin biz refaktoring mavzusida alohida maqola tayyorlaymiz - ya'ni kod sifatini uning funksionalligini o'zgartirmasdan yaxshilash haqida. O'sha vaqtga kelib, butun loyiha ko'rinadi va nimani va qayerda yaxshilash mumkinligi aniq bo'ladi. Bizning holatlarimizda biz funksionallikni buzishdan maksimal darajada himoyalangan bo'lamiz, chunki ko'plab testlar yozilgan. Shuningdek, biz nimani xohlayotganimiz va oxirida nimaga erishganimiz haqida retrospektiv yozamiz. Bu juda foydali narsa: keling, olti oy oldin hamma narsa qanchalik to'g'ri ko'rilganini ko'rib chiqaylik. Hech bo'lmaganda bu men uchun juda qiziq. Agar kimdir o'zini qo'lda sinovchi sifatida sinab ko'rmoqchi bo'lsa, bizga yozing va biz hamkorlik qilamiz. Keling, ushbu loyihani birgalikda yanada yaxshilaylik! Shunday qilib, bu erda ular: olti oy oldin tasvirlangan ikkita vazifa: JRTB-8 va JRTB-9 . Men ushbu vazifalarni bajarish uchun nima qilish kerakligini ko'rib chiqishni boshladim va buyruqlarni ishga tushirish nuqtai nazaridan hamma narsa allaqachon tayyor ekanligini angladim. Bu sodir bo'ladi ...) Bu erda siz StartCommand ni , bajarish usulini ko'rishingiz mumkin :
@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);
}
Mantiq bu erda ishlaydi: agar bizning ma'lumotlar bazasida chatId tomonidan allaqachon shunday foydalanuvchi mavjud bo'lsa, biz uning uchun faol = haqiqiy maydonni o'rnatamiz. Va agar bunday foydalanuvchi bo'lmasa, biz yangisini yaratamiz. StopCommand -dagi /stop buyrug'i uchun ham xuddi shunday :
@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);
}
Ko'rinib turibdiki, ushbu buyruqni chaqirishda foydalanuvchi uchun faqat faol = noto'g'ri maydon o'rnatiladi. Va bu hammasi: foydalanuvchi yana bot bilan suhbatni faollashtirishga qaror qilganda, uning obunalari yashaydi va qanotlarda kutadi. Va vazifa allaqachon bajarilgan va yopilishi mumkin bo'lganga o'xshaydi. Lekin u erda yo'q edi. Eng muhim vazifa - obunadagi yangi maqolalar haqida ogohlantirish yaratish. Bu erda bu vazifalar to'liq yangilanadi va yakunlanadi. Ya'ni, biz yangi maqolalar haqida xabar berishni amalga oshirmagunimizcha, uni yopish mumkin emas. Shuning uchun, keling, JRTB-4 vazifasini bajaraylik - har 20 daqiqada chek yaratish va yangi maqolalar haqida bildirishnomalar. Do'stlar! Loyiha uchun yangi kod qachon chiqarilganini darhol bilishni xohlaysizmi? Yangi maqola qachon chiqadi? tg kanalimga qo'shiling . U erda men maqolalarimni, fikrlarimni, ochiq manbali ishlanmalarimni birgalikda to'playman.

Biz JRTB-4 ni amalga oshiramiz

Ushbu vazifaning bir qismi sifatida nima qilishimiz kerak:
  1. Vaqti-vaqti bilan ma'lumotlar bazasida obuna bo'lgan barcha guruhlarga tashrif buyuradigan, maqolalarni nashr etilgan sana bo'yicha saralaydigan va oxirgi nashrning identifikatori GroupSub-dagi qiymatga mos kelishini tekshiradigan ish yarating. Agar u mos kelmasa, unda oxirgi marta qancha maqola chop etilganini aniq tushunishingiz kerak. Biz GroupSub7-dagi last_article_id ni joriy holatga yangilaymiz.

  2. Chop etilgan maqolalar ro'yxatini topganimizdan so'ng, biz ushbu guruhlar uchun barcha FAOL foydalanuvchilarni topamiz va ularga yangi maqolalar haqida bildirishnoma yuboramiz.

Buning uchun biz Spring Scheduler kabi narsadan foydalanamiz. Bu Spring Framework-dagi mexanizm bo'lib, uning yordamida siz ma'lum bir vaqtda bajariladigan vazifalarni yaratishingiz mumkin. Yoki har 15-20-40 daqiqada, yoki har payshanba kuni soat 15:30da yoki boshqa variantda. Ular ingliz tilidan olingan iz qog'ozi - joba deb ham ataladi. Biz bu vazifani bajarar ekanmiz, men ataylab yangi maqolalarni qidirishda bitta kamchilikni qoldiraman. Bu juda kam uchraydi va men ushbu vazifani qo'lda sinab ko'rgan vaziyatda paydo bo'ldi. Buning uchun siz maqolalarni qidirish uchun mijoz yozishingiz kerak. Buning uchun biz allaqachon tanish bo'lgan Swagger API dan foydalanamiz . Post-kontroller mavjud. Biz faqat ma'lum filtrlar yordamida maqolalar to'plamini qidirishdan manfaatdormiz:
/api/1.0/rest/posts Filtrlar bo'yicha xabarlarni oling
Biz bu talab bilan ishlaymiz. Unda bizga nima kerak? Muayyan guruhga tegishli maqolalar ro'yxatini oling va ular nashr etilgan sana bo'yicha saralanishi kerak. Shunday qilib, biz oxirgi 15 ta maqolani olishimiz va ma'lumotlar bazasidan lastArticleId asosida yangi nashrlar nashr etilganligini tekshirishimiz mumkin . Agar mavjud bo'lsa, biz ularni qayta ishlash va foydalanuvchiga yuborish uchun topshiramiz. Shunday qilib, biz JavaRushPostClient yozishimiz kerak .

Biz JavaRushPostClient-ni yozamiz

Bu erda biz APIda bizga yuborilgan barcha so'rovlarni qoplashga harakat qilmaymiz va faqat o'zimizga kerak bo'lganini yaratamiz. Shunday qilib, biz bir vaqtning o'zida ikkita maqsadga erishamiz:
  1. Biz arizamizni yozish jarayonini tezlashtiramiz.

  2. Biz bu ishni jamiyatimizga yordam berishni istagan va o'zini ishlab chiquvchi sifatida sinab ko'rishga qaror qilganlarga qoldiramiz. Buning uchun MVPdan keyin bajarilishi mumkin bo'lgan vazifalarni bajaraman.

Shunday qilib, qilaylik. Swagger UI -dagi Modellar bo'limiga so'rov berish uchun biz quyidagi DTO'larni yaratamiz:"A dan Zgacha Java loyihasi": Maqolalarga mijoz qo'shish - 2

BaseUserInfo:

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

Til:

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
}

Yoqtirgan ma'lumotlari:

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

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

   private Integer count;
   private LikeStatus status;
}

LikeStatus:

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
}

Post turi:

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

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

UserPublicStatus:

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
}
Ushbu DTOlarning barchasiga asoslanib, maqolalarni olish uchun asosiy sinfni yozamiz:

Post ma'lumoti:

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;

}
Endi ishlash uchun interfeys va uni amalga oshirishni yaratamiz. Maqolalar bilan ishlash uchun bizga faqat bitta usul kerak bo'ladi:

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 ikkita argumentni oladi: guruh identifikatori va bot allaqachon joylashtirgan maqolaning oxirgi identifikatori. Shuning uchun, lastPostId bilan maqoladan kechroq chop etilgan barcha maqolalar uzatiladi . Va uni amalga oshirish:
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;
   }
}
Biz so'rovga bir nechta filtrlarni qo'shamiz:
  • order = NEW - ro'yxatda birinchi navbatda yangilari bo'lishi uchun;
  • groupKid = groupId - faqat ma'lum guruhlarni qidirish;
  • limit = 15 - biz so'rov bo'yicha maqolalar sonini cheklaymiz. Bizning chastotamiz 15-20 daqiqa va biz bu vaqt ichida 15 (!) dan ortiq yozilmasligini kutamiz.
Keyinchalik, maqolalar topilganda, biz ro'yxatni ko'rib chiqamiz va yangilarini qidiramiz. Algoritm oddiy va intuitivdir. Agar siz uni yaxshilashni istasangiz, yozing). Keling, ushbu mijoz uchun oddiy test yozamiz:
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());
   }
}
Bu mijoz bilan aloqa bor yoki yo'qligini tekshiradigan juda oddiy test. U Java loyihalari guruhida 15 ta yangi maqola topadi, chunki men unga ushbu guruhdagi birinchi maqolaning identifikatorini beraman va ularning soni 15 dan ortiq... Ulardan allaqachon 22 tasi bor! Ularning soni bunchalik ko'p bo'ladi deb o'ylamagandim. Qanday qilib men tezda bilib oldim? Sizningcha, u ularni hisoblash uchun ketganmi? Yo'q) Men sveger ishlatdim va ma'lum bir guruh uchun maqolalar sonini ko'rib chiqdim. Aytgancha, siz boshqalarga shunday qarashingiz mumkin ... Va RANDOM guruhida qancha maqola bor? ... Men sizga hozir aytaman: ulardan 1062 tasi bor! Jiddiy miqdor.

Birinchi qismning oxiri

Bu erda biz mijoz bilan ishlashni maqola bo'yicha qo'shdik. Biz allaqachon hamma narsani qildik, bu safar hamma narsa oddiy va tez bo'lishi kerak deb o'ylayman. Keyingi maqolada Spring Scheduler qo'shamiz va FindNewArticleService ni yozamiz . Xo'sh, odatdagidek, like bosing - obuna bo'ling - qo'ng'iroq qiling , loyihamizga yulduz bering , sharhlar yozing va maqolani baholang! O'qiganingiz uchun barchangizga rahmat - tez orada ko'rishguncha!

Seriyadagi barcha materiallar ro'yxati ushbu maqolaning boshida.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION