JavaRush /Blog Jawa /Random-JV /Nambahake Spring Scheduler - "Proyek Java saka A nganti Z...

Nambahake Spring Scheduler - "Proyek Java saka A nganti Z"

Diterbitake ing grup
Halo kabeh, kanca-kanca sing daktresnani. Ing artikel sadurunge , kita nyiapake klien kanggo nggarap JavaRush API kanggo artikel. Saiki kita bisa nulis logika kanggo proyek kita, sing bakal dieksekusi saben 15 menit. Persis kaya sing ditampilake ing diagram iki: "Proyek Java saka A nganti Z": Nambahake Spring Scheduler - 1Saben 15 menit proyek bakal diluncurake (miturut pendapat kita, mung cara ing kelas tartamtu), sing ditindakake ing latar mburi aplikasi utama lan nindakake ing ngisor iki:
  1. Temokake ing kabeh klompok sing ana ing database kita artikel anyar sing diterbitake sawise eksekusi sadurunge.

    Skema iki nemtokake klompok sing luwih cilik - mung sing nganggo pangguna aktif. Ing wektu iku katon logis kanggo kula, nanging saiki aku ngerti manawa ana pangguna aktif sing langganan grup tartamtu utawa ora, sampeyan isih kudu nyimpen artikel paling anyar sing diproses bot. Kahanan bisa kedadeyan nalika pangguna anyar langsung nampa kabeh artikel sing diterbitake wiwit grup iki dipateni. Iki ora samesthine prilaku, lan kanggo ngindhari iku, kita kudu njaga grup kasebut saka database kita sing saiki ora duwe panganggo aktif up-to-date.
  2. Yen ana artikel anyar, gawe pesen kanggo kabeh pangguna sing aktif langganan grup iki. Yen ora ana artikel anyar, kita mung ngrampungake karya kasebut.

Ngomong-ngomong, aku wis kasebut ing saluran TG-ku yen bot wis kerja lan ngirim artikel anyar adhedhasar langganan. Ayo miwiti nulis FindNewArtcileService . Kabeh karya telusuran lan ngirim pesen bakal ditindakake ing kana, lan pakaryan mung bakal mbukak metode layanan iki:

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();
}
Prasaja banget, bener? Iki minangka inti, lan kabeh kesulitan bakal ana ing implementasine:
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);
   }
}
Ing kene kita bakal ngrampungake kabeh kanthi urutan:
  1. Nggunakake groupService kita nemokake kabeh grup sing ana ing database.

  2. Banjur kita nyebar menyang kabeh kelompok lan saben kita nelpon klien digawe ing artikel pungkasan - javaRushPostClient.findNewPosts .

  3. Sabanjure, nggunakake metode setNewArticleId , kita nganyari ID artikel artikel anyar sing paling anyar supaya database ngerti yen kita wis ngolah sing anyar.

  4. Lan nggunakake kasunyatan manawa GroupSub duwe koleksi pangguna, kita ngliwati sing aktif lan ngirim kabar babagan artikel anyar.

Kita ora bakal ngrembug apa pesen saiki, iku ora penting banget kanggo kita. Ingkang utama yaiku cara kasebut bisa digunakake. Logika kanggo nggoleki artikel anyar lan ngirim kabar wis siyap, supaya sampeyan bisa nerusake nggawe proyek.

Nggawe FindNewArticleJob

Kita wis ngomong babagan apa SpringScheduler, nanging ayo mbaleni kanthi cepet: minangka mekanisme ing kerangka Spring kanggo nggawe proses latar mburi sing bakal ditindakake ing wektu tartamtu sing kita setel. Apa sing sampeyan butuhake kanggo iki? Langkah pisanan yaiku nambah anotasi @EnableScheduling menyang kelas input musim semi:
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);
   }

}
Langkah kapindho yaiku nggawe kelas, nambah menyang ApplicationContext lan nggawe metode sing bakal ditindakake kanthi periodik. Kita nggawe paket proyek ing tingkat sing padha karo repositori, layanan, lan liya-liyane, lan ing kana kita nggawe kelas 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));
   }
}
Kanggo nambah kelas iki menyang Konteks Aplikasi aku nggunakake @Component anotasi . Lan supaya metode ing kelas ngerti yen kudu ditindakake sacara periodik, aku nambahake anotasi kanggo metode: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Nanging kita nyetel ing file application.properties:
bot.recountNewArticleFixedRate = 900000
Ing kene regane ing milliseconds. Iku bakal 15 menit. Ing cara iki, kabeh iku prasaja: Aku nambah metrik super prasaja kanggo aku ing log kanggo ngetung panelusuran kanggo artikel anyar, supaya ing paling kira-kira ngerti carane cepet iku bisa.

Nguji fungsi anyar

Saiki kita bakal nyoba ing test bot kita. Nanging carane? Aku ora bakal mbusak artikel saben wektu kanggo nuduhake yen kabar wis teka? Mesthi ora. Kita mung bakal ngowahi data ing database lan miwiti aplikasi kasebut. Aku bakal nyoba ing server test. Kanggo nindakake iki, ayo langganan sawetara grup. Nalika langganan rampung, grup bakal diwenehi ID saiki saka artikel paling anyar. Ayo menyang database lan ngganti nilai loro artikel bali. Akibaté, kita ngarepake bakal ana akeh artikel kaya sing kita setel lastArticleId sadurunge . "Proyek Java saka A nganti Z": Nambahake Spring Scheduler - 2Sabanjure, pindhah menyang situs kasebut, urutake artikel ing grup proyek Java - sing anyar dhisik - lan pindhah menyang artikel katelu saka dhaptar: "Proyek Jawa saka A nganti Z": Nambahake Spring Scheduler - 3Ayo menyang artikel ngisor lan saka baris alamat entuk artikel Id - 3313: "Proyek Java saka A nganti Z": Nambahake Spring Scheduler - 4Sabanjure , pindhah menyang MySQL Workbench lan ganti nilai lastArticleId dadi 3313. Ayo ndeleng manawa klompok kasebut ana ing basis data: "Proyek Java saka A nganti Z": Nambahake Spring Scheduler - 5Lan kanggo iki, kita bakal nglakokake prentah kasebut: "Proyek Java saka A nganti Z": Nambahake Spring Scheduler - 6Lan iku, saiki sampeyan kudu ngenteni nganti peluncuran proyek sabanjure. goleki artikel anyar. Kita ngarepake nampa rong pesen babagan artikel anyar saka grup proyek Java. Kaya sing dikandhakake, asile ora suwe: "Proyek Java saka A nganti Z": Nambahake Spring Scheduler - 7Pranyata bot kasebut kerja kaya sing dikarepake.

Ending

Kaya biasane, kita nganyari versi ing pom.xml lan nambah entri menyang RELEASE_NOTES supaya riwayat karya disimpen lan sampeyan bisa tansah bali lan ngerti apa sing wis diganti. Mulane, kita nambah versi kanthi siji unit:
<version>0.7.0-SNAPSHOT</version>
Lan nganyari RELEASE_NOTES:
## 0.7.0-SNAPSHOT * JRTB-4: nambah kemampuan kanggo ngirim kabar babagan artikel anyar * JRTB-8: nambah kemampuan kanggo nyetel pangguna telegram sing ora aktif * JRTB-9: nambah kemampuan kanggo nyetel pangguna aktif lan / utawa miwiti nggunakake.
Saiki sampeyan bisa nggawe panjalukan narik lan ngunggah owah-owahan anyar. Punika panjalukan narik kanthi kabeh owah-owahan ing rong bagean: STEP_8 . Apa sabanjure? Kayane kabeh wis siyap lan, kaya sing dikandhakake, bisa dadi produksi, nanging isih ana sawetara perkara sing dakkarepake. Contone, ngatur karya admin kanggo bot, nambah lan nambah kemampuan kanggo nyetel. Iku uga apik kanggo mbukak kode sadurunge rampung lan ndeleng apa ana bab sing bisa refactored. Aku wis bisa ndeleng desynchronization ing jeneng artikel / kirim. Ing pungkasan, kita bakal nindakake retrospektif babagan apa sing direncanakake lan apa sing ditampa. Lan apa sing arep sampeyan tindakake ing mangsa ngarep? Saiki aku bakal nuduhake sampeyan ide sing cukup kasar sing bisa lan bakal katon ing wayah awan: nggawe wiwitan springboot sing bakal duwe kabeh fungsi kanggo nggarap bot telegram lan nggoleki artikel. Iki bakal nggawe bisa nggabungake pendekatan lan digunakake kanggo bot telegram liyane. Iki bakal nggawe proyek iki luwih gampang diakses wong liya lan bisa entuk manfaat luwih akeh. Iki minangka salah sawijining gagasan. Ide liyane yaiku luwih jero babagan pangembangan kabar. Nanging kita bakal ngomong babagan iki mengko. Matur nuwun kabeh kanggo perhatian sampeyan, kaya biasane: kaya - langganan - lonceng , lintang kanggo proyek kita , komentar lan menehi rating artikel! Matur nuwun kanggo kabeh sing wis maca.

Dhaptar kabeh materi ing seri kasebut ana ing wiwitan artikel iki.

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