JavaRush /Java blogi /Random-UZ /Bahor rejalashtiruvchisini qo'shish - "A dan Zgacha Java ...

Bahor rejalashtiruvchisini qo'shish - "A dan Zgacha Java loyihasi"

Guruhda nashr etilgan
Hammaga salom aziz do'stlarim. Oldingi maqolada biz maqolalar uchun JavaRush API bilan ishlash uchun mijoz tayyorladik. Endi biz har 15 daqiqada bajariladigan ishimiz uchun mantiqni yozishimiz mumkin. Aynan ushbu diagrammada ko'rsatilganidek: “A dan Zgacha Java loyihasi”: Spring Scheduler qo'shish - 1har 15 daqiqada asosiy dastur fonida bajariladigan va quyidagilarni bajaradigan ish (bizning fikrimizcha, ma'lum bir sinfdagi usul) ishga tushiriladi:
  1. Bizning ma'lumotlar bazamizdagi barcha guruhlarda oldingi bajarilganidan keyin nashr etilgan yangi maqolalarni topadi.

    Ushbu sxema kichikroq guruhlarni belgilaydi - faqat faol foydalanuvchilari bo'lganlar. O'sha paytda bu menga mantiqiy tuyuldi, ammo hozir tushundimki, ma'lum bir guruhga obuna bo'lgan faol foydalanuvchilar bor yoki yo'qligidan qat'i nazar, siz hali ham bot tomonidan qayta ishlangan so'nggi maqolani yangilab turishingiz kerak. Vaziyat yangi foydalanuvchi ushbu guruh o'chirilganidan keyin chop etilgan barcha maqolalarni darhol qabul qilganda paydo bo'lishi mumkin. Bu kutilgan xatti-harakat emas va bunga yo'l qo'ymaslik uchun hozirda faol foydalanuvchilari mavjud bo'lmagan guruhlarni ma'lumotlar bazasidan saqlashimiz kerak.
  2. Agar yangi maqolalar bo'lsa, ushbu guruhga faol obuna bo'lgan barcha foydalanuvchilar uchun xabarlar yarating. Agar yangi maqolalar bo'lmasa, biz shunchaki ishni yakunlaymiz.

Aytgancha, men allaqachon TG kanalimda bot allaqachon ishlayotganini va obunalar asosida yangi maqolalar yuborayotganini aytib o'tgandim . FindNewArtcileService yozishni boshlaylik . Xabarlarni qidirish va jo'natish bo'yicha barcha ishlar u erda amalga oshiriladi va ish faqat ushbu xizmat usulini ishga tushiradi:

FindNewArticleService:

package com.github.javarushcommunity.jrtb.service;

/**
* Service for finding new articles.
*/
public interface FindNewArticleService {

   /**
    * Find new articles and notify subscribers about it.
    */
   void findNewArticles();
}
Juda oddiy, to'g'rimi? Bu uning mohiyati va barcha qiyinchiliklar amalga oshirishda bo'ladi:
package com.github.javarushcommunity.jrtb.service;

import com.github.javarushcommunity.jrtb.javarushclient.JavaRushPostClient;
import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class FindNewArticleServiceImpl implements FindNewArticleService {

   public static final String JAVARUSH_WEB_POST_FORMAT = "https://javarush.com/groups/posts/%s";

   private final GroupSubService groupSubService;
   private final JavaRushPostClient javaRushPostClient;
   private final SendBotMessageService sendMessageService;

   @Autowired
   public FindNewArticleServiceImpl(GroupSubService groupSubService,
                                    JavaRushPostClient javaRushPostClient,
                                    SendBotMessageService sendMessageService) {
       this.groupSubService = groupSubService;
       this.javaRushPostClient = javaRushPostClient;
       this.sendMessageService = sendMessageService;
   }


   @Override
   public void findNewArticles() {
       groupSubService.findAll().forEach(gSub -> {
           List<PostInfo> newPosts = javaRushPostClient.findNewPosts(gSub.getId(), gSub.getLastArticleId());

           setNewLastArticleId(gSub, newPosts);

           notifySubscribersAboutNewArticles(gSub, newPosts);
       });
   }

   private void notifySubscribersAboutNewArticles(GroupSub gSub, List<PostInfo> newPosts) {
       Collections.reverse(newPosts);
       List<String> messagesWithNewArticles = newPosts.stream()
               .map(post -> String.format("✨Вышла новая статья <b>%s</b> в группе <b>%s</b>.✨\n\n" +
                               "<b>Описание:</b> %s\n\n" +
                               "<b>Ссылка:</b> %s\n",
                       post.getTitle(), gSub.getTitle(), post.getDescription(), getPostUrl(post.getKey())))
               .collect(Collectors.toList());

       gSub.getUsers().stream()
               .filter(TelegramUser::isActive)
               .forEach(it -> sendMessageService.sendMessage(it.getChatId(), messagesWithNewArticles));
   }

   private void setNewLastArticleId(GroupSub gSub, List<PostInfo> newPosts) {
       newPosts.stream().mapToInt(PostInfo::getId).max()
               .ifPresent(id -> {
                   gSub.setLastArticleId(id);
                   groupSubService.save(gSub);
               });
   }

   private String getPostUrl(String key) {
       return String.format(JAVARUSH_WEB_POST_FORMAT, key);
   }
}
Bu erda biz hamma narsani tartibda hal qilamiz:
  1. groupService- dan foydalanib, biz ma'lumotlar bazasidagi barcha guruhlarni topamiz.

  2. Keyin biz barcha guruhlarga tarqalamiz va har biri uchun oxirgi maqolada yaratilgan mijozni chaqiramiz - javaRushPostClient.findNewPosts .

  3. Keyinchalik, setNewArticleId usulidan foydalanib , biz so'nggi yangi maqolamizning maqola identifikatorini yangilaymiz, shunda ma'lumotlar bazasi yangilarini qayta ishlaganimizni biladi.

  4. Va GroupSub-da foydalanuvchilar to'plami mavjudligidan foydalanib, biz faollar orqali o'tamiz va yangi maqolalar haqida bildirishnomalar yuboramiz.

Biz hozir xabar nima ekanligini muhokama qilmaymiz, bu biz uchun unchalik muhim emas. Asosiysi, usul ishlaydi. Yangi maqolalarni qidirish va bildirishnomalarni yuborish mantig'i tayyor, shuning uchun siz ish yaratishga o'tishingiz mumkin.

FindNewArticleJob yarating

Biz allaqachon SpringScheduler nima ekanligi haqida gapirgan edik, lekin buni tezda takrorlaymiz: bu biz belgilagan ma'lum bir vaqtda ishlaydigan fon jarayonini yaratish uchun Spring doirasidagi mexanizm. Buning uchun sizga nima kerak? Birinchi qadam, bizning bahorgi kirish sinfimizga @EnableScheduling izohini qo'shishdir :
package com.github.javarushcommunity.jrtb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
public class JavarushTelegramBotApplication {

   public static void main(String[] args) {
       SpringApplication.run(JavarushTelegramBotApplication.class, args);
   }

}
Ikkinchi qadam sinf yaratish, uni ApplicationContext- ga qo'shish va unda vaqti-vaqti bilan bajariladigan usulni yaratishdir. Biz ombor, xizmat va boshqalar bilan bir xil darajadagi ish paketini yaratamiz va u erda FindNewArticleJob sinfini yaratamiz :
package com.github.javarushcommunity.jrtb.job;

import com.github.javarushcommunity.jrtb.service.FindNewArticleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
* Job for finding new articles.
*/
@Slf4j
@Component
public class FindNewArticlesJob {

   private final FindNewArticleService findNewArticleService;

   @Autowired
   public FindNewArticlesJob(FindNewArticleService findNewArticleService) {
       this.findNewArticleService = findNewArticleService;
   }

   @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}")
   public void findNewArticles() {
       LocalDateTime start = LocalDateTime.now();

       log.info("Find new article job started.");

       findNewArticleService.findNewArticles();

       LocalDateTime end = LocalDateTime.now();

       log.info("Find new articles job finished. Took seconds: {}",
               end.toEpochSecond(ZoneOffset.UTC) - start.toEpochSecond(ZoneOffset.UTC));
   }
}
Ushbu sinfni Ilova kontekstiga qo'shish uchun men @Component izohidan foydalandim . Va sinf ichidagi usul uni vaqti-vaqti bilan ishga tushirish kerakligini bilishi uchun men usulga izoh qo'shdim: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Lekin biz uni application.properties faylida o'rnatdik:
bot.recountNewArticleFixedRate = 900000
Bu erda qiymat millisekundlarda. 15 daqiqa bo'ladi. Bu usulda hamma narsa oddiy: men hech bo'lmaganda uning qanchalik tez ishlashini tushunish uchun yangi maqolalarni qidirishni hisoblash uchun jurnallarga o'zim uchun juda oddiy ko'rsatkichni qo'shdim.

Yangi funksionallikni sinab ko'rish

Endi biz test botimizda sinab ko'ramiz. Lekin qanday? Bildirishnomalar kelganligini ko'rsatish uchun har safar maqolalarni o'chirmaymanmi? Albatta yo'q. Biz shunchaki ma'lumotlar bazasidagi ma'lumotlarni tahrir qilamiz va dasturni ishga tushiramiz. Men uni sinov serverimda sinab ko'raman. Buning uchun keling, qandaydir guruhga obuna bo'laylik. Obuna tugallangach, guruhga oxirgi maqolaning joriy identifikatori beriladi. Keling, ma'lumotlar bazasiga o'tamiz va ikki maqolaning qiymatini o'zgartiramiz. Natijada, biz lastArticleId ga avvalroq o'rnatganimizdek, shuncha maqola bo'lishini kutamiz . "A dan Zgacha Java loyihasi": Bahor rejalashtiruvchisini qo'shish - 2Keyinchalik, biz saytga o'tamiz, Java loyihalari guruhidagi maqolalarni saralaymiz - birinchi navbatda yangilari - va ro'yxatdagi uchinchi maqolaga o'tamiz: "Java-проект от А до Я": Добавляем Spring Scheduler - 3Pastki maqolaga o'tamiz va manzil satridan biz maqolani olamiz Id - 3313: "Java-проект от А до Я": Добавляем Spring Scheduler - 4Keyingi , MySQL Workbench-ga o'ting va lastArticleId qiymatini 3313 ga o'zgartiring. Keling, bunday guruh ma'lumotlar bazasida mavjudligini ko'rib chiqaylik: "Java-проект от А до Я": Добавляем Spring Scheduler - 5Va buning uchun biz buyruqni bajaramiz: "Java-проект от А до Я": Добавляем Spring Scheduler - 6Va tamom, endi ishning keyingi ishga tushirilishini kutish kerak. yangi maqolalarni qidiring. Java loyihalari guruhidan yangi maqola haqida ikkita xabar olishni kutamiz. Ular aytganidek, natija uzoq kutilgani yo'q: "Java-проект от А до Я": Добавляем Spring Scheduler - 7ma'lum bo'lishicha, bot biz kutgandek ishlagan.

Tugatish

Har doimgidek, biz pom.xml versiyasini yangilaymiz va RELEASE_NOTES-ga yozuv qo'shamiz, shunda ish tarixi saqlanadi va siz har doim orqaga qaytib, nima o'zgarganini tushunishingiz mumkin. Shuning uchun biz versiyani bir birlikka oshiramiz:
<version>0.7.0-SNAPSHOT</version>
Va RELEASE_NOTES-ni yangilang:
## 0.7.0-SNAPSHOT * JRTB-4: yangi maqolalar haqida bildirishnomalarni yuborish imkoniyati qo'shildi * JRTB-8: nofaol telegram foydalanuvchisini sozlash imkoniyati qo'shildi * JRTB-9: faol foydalanuvchini sozlash va/yoki undan foydalanishni boshlash uchun qo'shilgan imkoniyat.
Endi siz tortishish so'rovini yaratishingiz va yangi o'zgarishlarni yuklashingiz mumkin. Mana ikki qismdan iborat barcha o'zgarishlar bilan tortish so'rovi: STEP_8 . Keyin nima? Aftidan, hamma narsa tayyor va biz aytganimizdek, ishlab chiqarishga kirishishi mumkin, ammo men hali ham qilmoqchi bo'lgan narsalar bor. Masalan, bot uchun administratorlarning ishini sozlang, ularni qo'shing va ularni sozlash qobiliyatini qo'shing. Tugatishdan oldin kodni ko'rib chiqish va qayta tiklash mumkin bo'lgan narsalar mavjudligini ko'rish ham yaxshi fikr. Maqola/post nomidagi sinxronizatsiyani allaqachon ko'rishim mumkin. Oxir-oqibat, biz rejalashtirgan va olgan narsalarimizni retrospektiv qilamiz. Va kelajakda nima qilishni xohlaysiz? Endi men siz bilan kunning yorug‘ligini ko‘ra oladigan juda qo‘pol g‘oyani baham ko‘raman: telegram bot bilan ishlash va maqolalarni qidirish uchun barcha funksiyalarga ega bo‘lgan bahorgi starter yaratish. Bu yondashuvni birlashtirish va uni boshqa telegram botlari uchun ishlatish imkonini beradi. Bu ushbu loyihani boshqalar uchun qulayroq qiladi va ko'proq odamlarga foyda keltirishi mumkin. Bu fikrlardan biri. Yana bir fikr bildirishnomalarni ishlab chiqishga chuqurroq kirishdir. Ammo bu haqda biroz keyinroq gaplashamiz. E'tiboringiz uchun barchangizga rahmat, odatdagidek: layk - obuna bo'ling - qo'ng'iroq qiling , loyihamiz uchun yulduzcha qo'ying , sharh qoldiring va maqolaga baho bering! O'qiganingiz uchun barchaga rahmat.

Seriyadagi barcha materiallar ro'yxati ushbu maqolaning boshida.

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