JavaRush /Java блогу /Random-KY /Жазгы графигин кошуу - "Адан Яга чейин Java долбоору"
Roman Beekeeper
Деңгээл

Жазгы графигин кошуу - "Адан Яга чейин Java долбоору"

Группада жарыяланган
Баарыңарга салам, кымбаттуу досторум. Мурунку макалада биз макалалар үчүн JavaRush API менен иштөө үчүн кардарды даярдаганбыз. Эми ар бир 15 мүнөттө аткарыла турган жумушубуздун логикасын жаза алабыз. Дал ушул диаграммада көрсөтүлгөндөй: "Java долбоору Адан Яга": Жазгы Пландаштыруучу кошуу - 1Ар бир 15 мүнөт сайын негизги тиркеменин фонунда аткарылуучу жана төмөнкүлөрдү аткарган жумуш (биздин оюбузча, белгилүү бир класстагы ыкма) ишке киргизилет:
  1. Биздин базадагы бардык топтордо мурунку аткарылгандан кийин жарыяланган жаңы макалаларды табат.

    Бул схема топтордун азыраак санын көрсөтөт - активдүү колдонуучулары барлар гана. Ошол учурда бул мага логикалык көрүнгөн, бирок азыр мен түшүндүм, белгилүү бир топко жазылган активдүү колдонуучулар барбы же жокпу, сиз дагы эле бот иштеткен акыркы макаланы жаңыртуу керек. Жаңы колдонуучу бул топту өчүргөндөн бери жарыяланган макалалардын толук санын дароо алганда, кырдаал келип чыгышы мүмкүн. Бул күтүлбөгөн жүрүм-турум жана аны болтурбоо үчүн азыркы учурда активдүү колдонуучулары жок топторду биздин базадан сактап турушубуз керек.
  2. Жаңы макалалар бар болсо, бул топко активдүү жазылган бардык колдонуучулар үчүн билдирүүлөрдү түзүңүз. Эгерде жаңы макалалар жок болсо, биз жөн гана ишти бүтүрөбүз.

Баса, мен буга чейин TG каналымда бот иштеп жатканын жана жазылуулардын негизинде жаңы макалаларды жөнөтүп жатканын айттым . FindNewArtcileService жаза баштайлы . Издөө жана билдирүүлөрдү жөнөтүү боюнча бардык иштер ошол жерде ишке ашат жана жумуш бул кызматтын ыкмасын гана ишке киргизет:

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();
}
Абдан жөнөкөй, туурабы? Бул анын маңызы жана бардык кыйынчылык ишке ашырууда болот:
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);
   }
}
Бул жерде биз бардыгын ирети менен чечебиз:
  1. groupService аркылуу биз маалымат базасындагы бардык топторду табабыз.

  2. Андан кийин биз бардык топторго тарайбыз жана ар бири үчүн биз акыркы макалада түзүлгөн кардарды чакырабыз - javaRushPostClient.findNewPosts .

  3. Андан кийин, setNewArticleId ыкмасын колдонуп , биз акыркы жаңы макалабыздын макала идентификаторун жаңыртабыз, андыктан биздин маалымат базабыз жаңыларын иштетип койгонубузду билет.

  4. Ал эми GroupSub колдонуучулардын коллекциясына ээ экенин пайдаланып, биз активдүү колдонуучуларды аралап, жаңы макалалар тууралуу эскертмелерди жөнөтөбүз.

Биз азыр кабар эмне экенин талкуулабайбыз, бул биз үчүн өтө маанилүү эмес. Эң негизгиси, ыкма иштейт. Жаңы макалаларды издөө жана эскертмелерди жөнөтүү логикасы даяр, андыктан жумуш түзүүгө өтсөңүз болот.

FindNewArticleJob түзүңүз

SpringScheduler деген эмне экени тууралуу биз буга чейин эле айтканбыз, бирок аны тезинен кайталап көрөлү: бул жазгы рамкадагы фондо процессти түзүү механизми, ал биз белгилеген белгилүү бир убакытта иштей турган. Бул үчүн сага эмне керек? Биринчи кадам биздин жазгы киргизүү классыбызга @EnableScheduling annotationсын кошуу :
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);
   }

}
Экинчи кадам класс түзүү, аны ApplicationContext'ке кошуу жана анда мезгил-мезгor менен иштей турган ыкманы түзүү. Биз репозиторий, кызмат жана башкалар менен бирдей деңгээлде жумуш пакетин түзөбүз жана ал жерден FindNewArticleJob классын түзөбүз :
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));
   }
}
Бул классты Колдонмо контекстине кошуу үчүн мен @Component annotationсын колдондум . Класстын ичиндеги метод аны мезгил-мезгor менен иштетүү керек экенин бorши үчүн, мен методго annotation коштум: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Бирок биз аны application.properties файлына койдук:
bot.recountNewArticleFixedRate = 900000
Бул жерде маани миллисекундда. 15 мүнөт болот. Бул ыкмада бардыгы жөнөкөй: мен анын канчалык тез иштээрин түшүнүү үчүн, жаңы макалаларды издөөнү эсептөө үчүн журналдарга өзүм үчүн супер жөнөкөй метрика коштум.

Жаңы функцияларды текшерүү

Эми биз сыноо ботубузда сынап көрөбүз. Бирок кантип? Билдирүүлөр келгенин көрсөтүү үчүн макалаларды өчүрбөймбү? Албетте жок. Биз жөн гана маалымат базасындагы маалыматтарды түзөтүп, тиркемени ишке киргизебиз. Мен аны тесттик serverимде сынап көрөм. Бул үчүн, келгиле, кандайдыр бир группага жазылалы. Жазылуу аяктагандан кийин, топко акыркы макаланын учурдагы ID берилет. Келгиле, маалымат базасына барып, эки макаланын маанисин өзгөртөлү. Жыйынтыгында, биз lastArticleId дегенге мурункуга койгондой көп макалалар болот деп күтөбүз . "Java долбоору Адан Яга": Жазгы Пландаштыруучу кошуу - 2Андан кийин, биз сайтка барабыз, Java долбоорлорунун тобундагы макалаларды иреттейбиз - биринчи кезекте жаңылары - жана тизмеден үчүнчү макалага барабыз: "Java-проект от А до Я": Добавляем Spring Scheduler - 3Төмөнкү макалага баралы жана дарек тилкесинде Id - 3313 макаласын алабыз: "Java-проект от А до Я": Добавляем Spring Scheduler - 4Кийинки , MySQL Workbenchке өтүп, lastArticleId маанисин 3313 деп өзгөртүңүз. Келгиле, мындай топтун маалымат базасында бар экенин карап көрөлү: "Java-проект от А до Я": Добавляем Spring Scheduler - 5Ал үчүн биз буйрукту аткарабыз: "Java-проект от А до Я": Добавляем Spring Scheduler - 6Болду, эми жумуштун кийинки ишке киришине чейин күтүш керек. жаңы макалаларды издөө. Биз Java долбоорлор тобунан жаңы макала тууралуу эки билдирүүнү күтөбүз. Алар айткандай, натыйжа көп күткөн жок: "Java-проект от А до Я": Добавляем Spring Scheduler - 7Көрсө, бот биз күткөндөй иштеген.

Аяктоо

Адаттагыдай эле, биз pom.xml versionсын жаңыртабыз жана RELEASE_NOTESке жазууну кошобуз, андыктан жумуш тарыхы сакталып, сиз ар дайым артка кайтып, эмне өзгөргөнүн түшүнө аласыз. Ошондуктан, биз versionны бир бирдикке көбөйтөбүз:
<version>0.7.0-SNAPSHOT</version>
Жана RELEASE_NOTES жаңыртуу:
## 0.7.0-SNAPSHOT * JRTB-4: жаңы макалалар жөнүндө эскертмелерди жөнөтүү мүмкүнчүлүгү кошулду * JRTB-8: жигердүү эмес телеграмма колдонуучуну коюу мүмкүнчүлүгү кошулду * JRTB-9: жигердүү колдонуучуну орнотуу жана/же аны колдонууну баштоо үчүн кошумча мүмкүнчүлүк.
Эми сиз тартуу сурамын түзүп, жаңы өзгөртүүлөрдү жүктөй аласыз. Бул жерде эки бөлүктөн турган бардык өзгөртүүлөр менен тартуу өтүнүчү: STEP_8 . Кийинкиси эмне? Баардыгы даяр болуп, биз айткандай өндүрүшкө кирсе болот окшойт, бирок мен дагы деле жасай турган иштер бар. Мисалы, бот үчүн администраторлордун ишин конфигурациялаңыз, аларды кошуңуз жана аларды орнотуу мүмкүнчүлүгүн кошуңуз. Бүтүрүү алдында codeду карап чыгуу жана рефакторациялоо мүмкүн болгон нерселер бар-жогун көрүү жакшы идея. Мен макаланын/посттун аталышында десинхронизацияны көрө алам. Эң аягында биз эмнени пландап, эмне алганыбызды ретроспективага алабыз. Ал эми келечекте эмне кылгыңыз келет? Эми мен сиздер менен күндүн жарыгын көрө турган өтө одоно идея менен бөлүшөм: телеграмма боту менен иштөө жана макалаларды издөө үчүн бардык функцияларга ээ болгон жазгы стартер жасоо. Бул ыкманы унификациялоого жана аны башка телеграмма боттору үчүн колдонууга мүмкүндүк берет. Бул бул долбоорду башкалар үчүн жеткorктүү кылат жана көбүрөөк адамдарга пайда алып келет. Бул идеялардын бири. Дагы бир идея - билдирүүлөрдү иштеп чыгууга тереңирээк баруу. Бирок бул тууралуу бир аз кийинчерээк сүйлөшөбүз. Баарыңыздарга көңүл бурганыңыз үчүн рахмат, адаттагыдай эле: лайк - жазылуу - коңгуроо , биздин долбоорго жылдыз , комментарий жана макалага баа! Окуу үчүн баарына рахмат.

Сериядагы бардык материалдардын тизмеси ушул макаланын башында.

Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION