JavaRush /Blog Java /Random-MS /Menambah pelanggan pada artikel - "Projek Java dari A hin...

Menambah pelanggan pada artikel - "Projek Java dari A hingga Z"

Diterbitkan dalam kumpulan
Hello semua, kawan-kawan yang dikasihi. Langkah demi langkah kami semakin hampir kepada matlamat kami - untuk menjadi MVP projek kami - JavaRush Telegram Bot. Seperti yang saya katakan dalam artikel lepas, hanya tinggal 5 tugasan sahaja. Hari ini kita akan membincangkan dua daripadanya. "Projek Java dari A hingga Z": Menambah klien pada artikel - 1Saya ingin mengulangi bahawa projek itu tidak akan berakhir di sini. Saya masih mempunyai banyak idea dan visi tentang bagaimana projek ini harus dibangunkan, perkara baharu yang boleh ditambah kepadanya, apa yang boleh dilakukan dengan lebih baik. Sebelum MVP, kami akan membuat artikel berasingan mengenai topik pemfaktoran semula - iaitu tentang meningkatkan kualiti kod tanpa mengubah fungsinya. Pada masa itu, keseluruhan projek akan dapat dilihat dan akan jelas apa dan di mana boleh diperbaiki. Dalam kes kami, kami akan dilindungi secara maksimum daripada melanggar fungsi, kerana banyak ujian telah ditulis. Kami juga akan menulis retrospektif tentang apa yang kami mahu dan apa yang kami dapat pada akhirnya. Ini adalah perkara yang sangat berguna: mari kita lihat sejauh mana semuanya dilihat dengan betul enam bulan lalu. Sekurang-kurangnya ini sangat menarik bagi saya. Jika sesiapa ingin mencuba diri mereka sebagai penguji manual, tulis kepada kami dan kami akan bekerjasama. Mari kita jadikan projek ini lebih baik bersama-sama! Jadi, ini ialah: dua tugasan yang diterangkan enam bulan lalu: JRTB-8 dan JRTB-9 . Saya mula melihat apa yang perlu dilaksanakan untuk tugas-tugas ini, dan menyedari bahawa dari segi pelancaran arahan, semuanya sudah sedia. Ia berlaku...) Di sini, anda boleh melihat StartCommand , kaedah pelaksanaan :
@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);
}
Logiknya berfungsi di sini: jika pangkalan data kami sudah mempunyai pengguna sedemikian melalui chatId, kami hanya menetapkan medan aktif = benar untuknya. Dan jika tiada pengguna sedemikian, kami mencipta pengguna baharu. Sama untuk arahan /stop dalam 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);
}
Ia boleh dilihat bahawa apabila memanggil arahan ini, hanya medan aktif = palsu ditetapkan untuk pengguna. Dan itu sahaja: langganannya akan hidup dan menunggu apabila pengguna sekali lagi memutuskan untuk mengaktifkan sembang dengan bot. Dan nampaknya tugas itu telah pun selesai dan boleh ditutup. Tetapi ia tidak ada di sana. Tugas yang paling penting ialah membuat makluman tentang artikel baharu dalam langganan. Di sinilah tugasan ini akan dikemas kini dan diselesaikan sepenuhnya. Iaitu, sehingga kami melaksanakan pemberitahuan artikel baharu, ia tidak boleh ditutup. Oleh itu, mari kita uruskan tugas JRTB-4 - membuat semakan setiap 20 minit dan pemberitahuan tentang artikel baharu. Kawan-kawan! Adakah anda ingin mengetahui dengan segera apabila kod baharu untuk projek itu dikeluarkan? Bilakah artikel baru keluar? Sertai saluran tg saya . Di sana saya mengumpulkan artikel saya, pemikiran saya, pembangunan sumber terbuka saya bersama-sama.

Kami melaksanakan JRTB-4

Apa yang perlu kita lakukan sebagai sebahagian daripada tugas ini:
  1. Buat kerja yang secara berkala akan melawati semua kumpulan yang kami mempunyai langganan dalam pangkalan data, mengisih artikel mengikut tarikh penerbitan dan semak sama ada ID penerbitan terakhir sepadan dengan nilai dalam GroupSub. Jika ia tidak sepadan, maka anda perlu memahami dengan tepat berapa banyak artikel telah diterbitkan sejak kali terakhir. Kami mengemas kini last_article_id dalam GroupSub7 kepada keadaan semasa.

  2. Apabila kami telah menemui senarai artikel yang diterbitkan, kami menemui semua pengguna AKTIF untuk kumpulan ini dan menghantar pemberitahuan kepada mereka tentang artikel baharu.

Untuk melakukan ini, kami akan menggunakan perkara seperti Penjadual Spring. Ini ialah mekanisme dalam Rangka Kerja Spring, dengannya anda boleh membuat tugasan yang akan dilaksanakan pada masa tertentu. Sama ada setiap 15-20-40 minit, atau setiap Khamis pada 15:30 atau beberapa pilihan lain. Mereka juga dipanggil kertas surih dari bahasa Inggeris - joba. Semasa kita melakukan tugasan ini, saya akan sengaja meninggalkan satu kecacatan dalam pencarian artikel baru. Ia agak jarang berlaku dan hanya muncul dalam keadaan di mana saya menguji operasi tugas ini secara manual. Untuk melakukan ini, anda perlu menulis pelanggan untuk mencari artikel. Untuk melakukan ini, kami akan menggunakan API Swagger yang sudah biasa kepada kami . Terdapat post-controller. Kami hanya berminat untuk mencari koleksi artikel menggunakan penapis tertentu:
/api/1.0/rest/posts Dapatkan siaran melalui penapis
Kami akan bekerjasama dengan permintaan ini. Apa yang kita perlukan di dalamnya? Dapatkan senarai artikel yang tergolong dalam kumpulan tertentu, dan ia harus diisih mengikut tarikh penerbitan. Dengan cara ini kita boleh mengambil 15 artikel terakhir dan menyemak sama ada penerbitan baharu telah diterbitkan berdasarkan lastArticleId daripada pangkalan data kami. Jika ada, kami akan meneruskannya untuk diproses dan dihantar kepada pengguna. Jadi kita perlu menulis JavaRushPostClient .

Kami menulis JavaRushPostClient

Di sini kami tidak akan cuba untuk menampung semua permintaan yang dihantar kepada kami dalam API dan hanya akan mencipta permintaan yang kami perlukan. Dengan melakukan ini, kami mencapai dua matlamat sekaligus:
  1. Kami mempercepatkan proses menulis permohonan kami.

  2. Kami menyerahkan kerja ini kepada mereka yang ingin membantu komuniti kami dan memutuskan untuk mencuba diri mereka sebagai pembangun. Saya akan membuat tugasan untuk ini yang boleh diselesaikan selepas MVP.

Jadi mari kita lakukannya. Untuk menanyakan bahagian Model dalam UI Swagger, kami akan membuat DTO berikut:"Projek Java dari A hingga Z": Menambah klien pada artikel - 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;
}

Bahasa:

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
}

LikesInfo:

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
}

PostType:

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
}
Berdasarkan semua DTO ini, mari kita tulis kelas utama untuk menerima artikel:

Maklumat Pos:

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;

}
Sekarang mari kita cipta antara muka untuk digunakan dan pelaksanaannya. Kami hanya memerlukan satu kaedah untuk bekerja dengan artikel:

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 mengambil dua hujah: ID kumpulan dan ID terakhir artikel yang telah disiarkan oleh bot. Oleh itu, semua artikel yang diterbitkan lewat daripada artikel dengan lastPostId akan dihantar . Dan pelaksanaannya:
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;
   }
}
Kami menambah beberapa penapis pada permintaan:
  • pesanan = BARU - supaya senarai mengandungi yang baru dahulu;
  • groupKid = groupId - cari hanya untuk kumpulan tertentu;
  • had = 15 — kami mengehadkan bilangan artikel setiap permintaan. Kekerapan kami ialah 15-20 minit dan kami menjangkakan bahawa pada masa ini tidak LEBIH daripada 15 (!) akan ditulis.
Seterusnya, apabila kami telah menemui artikel, kami menyemak senarai dan mencari yang baharu. Algoritma adalah mudah dan intuitif. Jika anda ingin memperbaikinya, tulis). Mari kita tulis ujian mudah untuk pelanggan ini:
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());
   }
}
Ini adalah ujian yang sangat mudah yang memeriksa sama ada terdapat sebarang komunikasi dengan pelanggan sama sekali atau tidak. Dia menemui 15 artikel baharu dalam kumpulan projek Java, kerana saya memberinya ID artikel pertama dalam kumpulan ini, dan sudah ada lebih daripada 15 daripadanya... Sudah ada 22 daripadanya! Saya tidak menyangka akan ada begitu ramai daripada mereka. Bagaimana saya mengetahui dengan cepat? Adakah anda fikir dia pergi untuk mengira mereka? Tidak) Saya menggunakan swager dan melihat jumlah artikel untuk kumpulan tertentu. Ngomong-ngomong, anda boleh melihat cara ini pada orang lain... Dan berapa banyak artikel dalam kumpulan RANDOM?... Saya akan memberitahu anda sekarang: terdapat 1062 daripadanya! Jumlah yang serius.

Akhir bahagian pertama

Di sini kami telah menambah kerja dengan pelanggan mengikut artikel. Kami sudah melakukan segala-galanya, kali ini saya fikir semuanya harus mudah dan cepat. Dalam artikel seterusnya kami akan menambah Spring Scheduler dan menulis FindNewArticleService . Baiklah, seperti biasa, suka - langgan - bunyikan loceng , berikan projek kami bintang , tulis komen dan nilaikan artikel itu! Terima kasih semua kerana membaca - jumpa lagi!

Senarai semua bahan dalam siri ini adalah pada permulaan artikel ini.

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