JavaRush /Java Blog /Random-TW /我們正在新增訂閱一組文章的功能。(第 3 部分)-“Java 專案從頭到尾”
Roman Beekeeper
等級 35

我們正在新增訂閱一組文章的功能。(第 3 部分)-“Java 專案從頭到尾”

在 Random-TW 群組發布
你好,我們又見面了。這是 STEP_6 的最後一篇文章,我們將討論在其中討論為JRTB-6任務添加功能。在前面的兩篇文章(第 1 部分第 2 部分)中,我們已經準備好了您所需的幾乎所有內容。這部分是過程的高潮。對於所有從一開始就讀過本系列文章的人,我們深表敬意。這意味著您有足夠的動力去找到一份好工作。現在讓我們言歸正傳吧。「Java 專案從 A 到 Z」:新增訂閱一組文章的功能。 第 3 - 1 部分

我們實作 JRTB-6

這次我們將從電報機器人一側執行任務,因為更新資料庫的工作已全部完成,資料庫實體已配置並準備好工作。讓我們為CommandName新增一個新值- LIST_GROUP_SUB:
LIST_GROUP_SUB("/listGroupSub");
讓我們建立一個ListGroupSubCommand 指令:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.telegram.telegrambots.meta.api.objects.Update;

import javax.ws.rs.NotFoundException;
import java.util.stream.Collectors;

import static com.github.javarushcommunity.jrtb.command.CommandUtils.getChatId;

/**
* {@link Command} for getting list of {@link GroupSub}.
*/
public class ListGroupSubCommand implements Command {

   private final SendBotMessageService sendBotMessageService;
   private final TelegramUserService telegramUserService;

   public ListGroupSubCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
       this.sendBotMessageService = sendBotMessageService;
       this.telegramUserService = telegramUserService;
   }

   @Override
   public void execute(Update update) {
       //todo add exception handling
       TelegramUser telegramUser = telegramUserService.findByChatId(getChatId(update))
               .orElseThrow(NotFoundException::new);

       String message = "Я нашел все подписки на группы: \n\n";
       String collectedGroups = telegramUser.getGroupSubs().stream()
               .map(it -> "Группа: " + it.getTitle() + " , ID = " + it.getId() + " \n")
               .collect(Collectors.joining());

       sendBotMessageService.sendMessage(telegramUser.getChatId(), message + collectedGroups);
   }
}
這裡一切都盡可能簡單 - 我們使用現有的 chat_id 來獲取用戶,並且他對群組的所有訂閱都將收集在他的物件中。我們在第二部分中對此進行了設定。再次,我添加了//todo,這樣我就不會忘記添加對操作期間可能出現的異常的處理。下一步是透過向 CommandContainer 新增指令來更新 CommandContainer :
put(LIST_GROUP_SUB.getCommandName(), new GroupSubListCommand(sendBotMessageService, telegramUserService))
基本上就是這樣:現在您需要編寫更多測試,更新/help命令(添加新命令的描述)並透過 Telegram 測試新功能。讓我們為ListGroupSubCommand寫一個測試。由於命令的邏輯並不典型,因此我們將編寫一個測試,而不是像之前那樣 綁定到AbstractCommandTest類別:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.github.javarushcommunity.jrtb.command.CommandName.LIST_GROUP_SUB;

@DisplayName("Unit-level testing for ListGroupSubCommand")
public class ListGroupSubCommandTest {

   @Test
   public void shouldProperlyShowsListGroupSub() {
       //given
       TelegramUser telegramUser = new TelegramUser();
       telegramUser.setActive(true);
       telegramUser.setChatId("1");

       List<GroupSub> groupSubList = new ArrayList<>();
       groupSubList.add(populateGroupSub(1, "gs1"));
       groupSubList.add(populateGroupSub(2, "gs2"));
       groupSubList.add(populateGroupSub(3, "gs3"));
       groupSubList.add(populateGroupSub(4, "gs4"));

       telegramUser.setGroupSubs(groupSubList);

       SendBotMessageService sendBotMessageService = Mockito.mock(SendBotMessageService.class);
       TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);

       Mockito.when(telegramUserService.findByChatId(telegramUser.getChatId())).thenReturn(Optional.of(telegramUser));

       ListGroupSubCommand command = new ListGroupSubCommand(sendBotMessageService, telegramUserService);

       Update update = new Update();
       Message message = Mockito.mock(Message.class);
       Mockito.when(message.getChatId()).thenReturn(Long.valueOf(telegramUser.getChatId()));
       Mockito.when(message.getText()).thenReturn(LIST_GROUP_SUB.getCommandName());
       update.setMessage(message);

       String collectedGroups = "Я нашел все подписки на группы: \n\n" +
               telegramUser.getGroupSubs().stream()
                       .map(it -> "Группа: " + it.getTitle() + " , ID = " + it.getId() + " \n")
                       .collect(Collectors.joining());

       //when
       command.execute(update);

       //then
       Mockito.verify(sendBotMessageService).sendMessage(telegramUser.getChatId(), collectedGroups);
   }

   private GroupSub populateGroupSub(Integer id, String title) {
       GroupSub gs = new GroupSub();
       gs.setId(id);
       gs.setTitle(title);
       return gs;
   }
}

讓我們更新 /help 指令

在我們的例子中,/help命令充當使用機器人的文檔,因此我們必須記住更新它,以便用戶可以使用它。我們新增了兩個命令,所以讓我們更新即將出現的文字:
public static final String HELP_MESSAGE = String.format("✨Дотупные команды✨\n\n"

               + "Начать\\закончить работу с ботом:\n"
               + "%s - начать работу со мной\n"
               + "%s - приостановить работу со мной\n\n"

               + "Работа с подписками на группы:\n"
               + "%s - подписаться на группу статей\n"
               + "%s - получить список групп, на которые подписан\n\n"

               + "%s - получить помощь в работе со мной\n"
               + "%s - получить мою статистику использования\n",
       START.getCommandName(), STOP.getCommandName(), ADD_GROUP_SUB.getCommandName(),
       LIST_GROUP_SUB.getCommandName(), HELP.getCommandName(), STAT.getCommandName());
我還更新了機器人回應的文字:我這樣做是為了始終與用戶使用名字,否則就會有「你」和「你」......現在至少可以創建機器人工作中的某種聯繫。

測試更新後的機器人

我們在本地啟動我們的機器人並執行以下操作:
  1. 我們執行/start命令以確保測試案例中的用戶已添加到資料庫中。
  2. 我們執行/help命令 - 我們檢查一切是否正常,如我們所願。
  3. 接下來我們執行/addGroupSub指令。
  4. 從建議的群組 ID 清單中,我們新增了幾個群組 ID。
  5. 我們執行/listGroupSub命令以確保群組已註冊給使用者。
去!我們透過 docker-compose-test.yml 啟動資料庫並啟動 SpringBoot。接下來,前往我們的測試機器人並執行 /start 命令,然後執行/help「Java 專案從 A 到 Z」:新增訂閱一組文章的功能。 第 3 - 2 部分接下來,輸入命令/addGroupSub「Java 專案從 A 到 Z」:新增訂閱一組文章的功能。 第 3 - 3 部分下拉清單表明 Java 用戶端正在正常工作:我們擁有所有群組及其ID,命令的描述有助於(希望)理解我們接下來需要什麼,因此我們為訂閱添加了幾個群組:「Java 專案從 A 到 Z」:新增訂閱一組文章的功能。 第 3 - 4 部分現在我們有 5 個訂閱,因此我們可以運行/listGroupSub命令:然後我們得到了一些瘋狂的事情...目前尚不清楚為什麼標題「Java 專案從 A 到 Z」:新增訂閱一組文章的功能。 第 3 - 5 部分顯示沒有任何問題,但不是在這裡。讓我們去資料庫看看有什麼:資料庫中記錄了相同的問題,但僅限於那些帶有西里爾字母的問題。這意味著編碼存在一些問題。顯然,您需要配置資料庫以及連接資料庫的驅動程式。我們需要UTF-8。但要如何添加呢?經過幾分鐘在互聯網上搜索,我發現:驅動程式需要更新 url 變數。對於在 docker-compose 中設置 docker 映像,這是第一個鏈接,但答案不是第一個))因此,知道了這一點,讓我們更新屬性和 docker-compose 檔案。 「Java 專案從 A 到 Z」:新增訂閱一組文章的功能。 第 3 - 6 部分
application.properties:
spring.datasource.url=jdbc:mysql://jrtb-db:3306/jrtb_db?characterEncoding=UTF-8

application-test.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/dev_jrtb_db?characterEncoding=UTF-8

docker-compose.yml (добавил последнюю строку):
jrtb-db:
 image: mysql:5.7
 restart: always
 environment:
   MYSQL_USER: ${BOT_DB_USERNAME}
   MYSQL_PASSWORD: ${BOT_DB_PASSWORD}
   MYSQL_DATABASE: 'jrtb_db'
   MYSQL_ROOT_PASSWORD: 'root'
 ports:
   - '3306:3306'
 expose:
   - '3306'
 command: --character-set-server=utf8 --collation-server=utf8_general_ci

docker-compose-test.yml (добавил последнюю строку)
jrtb-db-dev:
 image: mysql:5.7
 restart: always
 environment:
   MYSQL_DATABASE: 'dev_jrtb_db'
   # So you don't have to use root, but you can if you like
   MYSQL_USER: 'dev_jrtb_db_user'
   # You can use whatever password you like
   MYSQL_PASSWORD: 'dev_jrtb_db_password'
   # Password for root access
   MYSQL_ROOT_PASSWORD: 'root'
 ports:
   # <Port exposed> : < MySQL Port running inside container>
   - '3306:3306'
 expose:
   # Opens port 3306 on the container
     - '3306'
 command: --character-set-server=utf8 --collation-server=utf8_general_ci
在這些更新之後,您需要刪除資料庫中的所有資料並重新開始。擦除非常簡單:您需要執行指令: docker-compose -f docker-compose-test.yml down ,然後所有資料和資料庫都會被刪除。並使用更新的編碼再次運行它: docker-compose -f docker-compose-test.uml up 資料庫已準備就緒。讓我們啟動更新的應用程式並看一下。我將快速瀏覽一遍並向您展示結果:「Java 專案從 A 到 Z」:新增訂閱一組文章的功能。 第 3 - 7 部分現在我們得到了我們想要的結果。現在這看起來像是事實。

結尾

現在我想我們可以完成這一步了。已經做了很多,真的很多。讓我們將應用程式版本更新為0.5.0-SNAPSHOT和 RELEASE_NOTES。
# 發行說明 ## 0.5.0-SNAPSHOT * JRTB-5:新增了群組訂閱功能 * JRTB-6:新增了取得群組訂閱清單的功能。
然後一切都像往常一樣:我們建立一個包含所有變更的新提交。主要是添加此步驟中完成的兩項任務的描述以用於報告目的。所以這是評論:
STEP_6 JRTB-5:新增了訂閱群組的功能 JRTB-6:新增了查看群組訂閱清單的功能。
這導致了 47 個文件的更改...這是一個很大的變化。雖然你無法從功能描述中看出。畢竟,要了解完整的深度,您需要知道您需要為 API 編寫 Java 用戶端,本質上是更新整個應用程式。事情就是這樣,在伺服器上工作 - 有很多工作,但客戶端的可見性很小...)) 朋友,我傳統上為您提供一種對我的工作表現出興趣的方法 - 訂閱github帳戶,加入電報頻道並寫下有關文章的問題,如果有不清楚的地方! 以下是拉取請求的鏈接,其中包含此STEP_6的更改。感謝大家的閱讀。更多內容即將推出 - 讓我們討論一下刪除訂閱、停用設定檔等等。不要切換))

此系列所有資料的清單位於本文開頭。

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