Всем привет! Сделал телеграм бота, который, в ответ на запрос "название города", отправляет данные о погоде на сегодня и завтра. Всё работает, теперь надо сделать, чтобы он работал в несколько потоков, чтобы не создавать очередь в случае, когда несколько пользователей одновременно отправляют запрос на погоду.
Код бота такой
public class Bot extends TelegramLongPollingBot {
private static final String NAME_OF_BOT = "MyWeather129Bot";
private static final String BOT_TOKEN = "657869679:AAGZ5xy_V5WyTDWy7Ex8HorP-UABJKT****";
public SqlMethods source;
public void onUpdateReceived(Update update){
Message message = update.getMessage();
if(message.getText().equals("/start")){
sendMSG(message, "Привет, "+ message.getChat().getFirstName()+"!"+ System.lineSeparator()+
"Для просмотра погоды нужно выбрать место нахождения." +
System.lineSeparator()+
"Для этого достаточно написать название населенного пункта и страну в чат" +
"(Например Sankt-Peterburg или Санкт-Петербург)");
}
else if(message != null && message.hasText() && !message.getText().equals("/start")) {
try {
sendMSG(message, Weather.getWeather(message.getText()));
sendMSG(message, WeatherTomorrow.getWeatherTomorrow(message.getText()));
} catch (IOException e) {
sendMSG(message, "Город не найден!напишите название населенного пункта в чат " +
"(Например Sankt-Peterburg или Санкт-Петербург)");
}
}
else if (message.getText().equals("/subscribe")) {
sendMSG(message, "Напишите название населённого пункта," +
"для которого вы хотите получать ежедневный прогноз погоды");
long id = message.getChatId();
String userName = message.getChat().getUserName();
String firstName = message.getChat().getFirstName();
String location = message.getText();
boolean subResult = source.addSubscriber(id, userName, firstName);
if (subResult) {
sendMSG(message, "Спасибо за подписку :)");
} else {
sendMSG(message, "Не удалось подписаться!");
}
}
else if (message.getText().equals("/unsubscribe")){
long deleteId = message.getChatId();
boolean unsubResult = source.deleteSubscriber(deleteId);
if(unsubResult){
sendMSG(message, "Вы отписались от прогноза погоды :(");
} else{
sendMSG(message, "Не удалось отписаться!");
}
}
else {
sendMSG(message, "напишите название населенного пункта в чат " +
"(Например Sankt-Peterburg или Санкт-Петербург)");
}
}
public void sendMSG(Message message, String text){
SendMessage sendMessage = new SendMessage();
sendMessage.enableMarkdown(true);
sendMessage.setChatId(message.getChatId().toString());
sendMessage.setReplyToMessageId(message.getMessageId());
sendMessage.setText(text);
try {
execute(sendMessage);
setButtons(sendMessage);
}catch (TelegramApiException e){
e.printStackTrace();
}
}
public void setButtons(SendMessage sendMessage){
ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup();
sendMessage.setReplyMarkup(replyKeyboardMarkup);
replyKeyboardMarkup.setSelective(true);
replyKeyboardMarkup.setOneTimeKeyboard(false);
replyKeyboardMarkup.setOneTimeKeyboard(false);
List<KeyboardRow> keyboardRowList = new ArrayList<>();
KeyboardRow keyboardFirstRow = new KeyboardRow();
keyboardRowList.add(keyboardFirstRow);
replyKeyboardMarkup.setKeyboard(keyboardRowList);
}
public String getBotUsername(){
return NAME_OF_BOT;
}
public String getBotToken(){
return BOT_TOKEN;
}
}
Класс Weather
public class Weather {
public static final String URL_SOURCE = "http://api.openweathermap.org/data/2.5/weather?q=";
public static final String API_KEY = "&APPID=3ad54740fd37f3f14a3a32a09f09cd25";
public static final String UNITS = "&units=metric";
public static final String LANG = "&lang=ru";
public static String getWeather(String message) throws IOException{
// get weather data from URL
URL url = new URL(URL_SOURCE + message + LANG + UNITS + API_KEY);
InputStreamReader reader = new InputStreamReader(url.openStream());
OneDayWeather todayWeatherData = null;
Gson todayWeatherGson = new Gson();
todayWeatherData = todayWeatherGson.fromJson(reader, OneDayWeather.class);
System.out.println("В городе " + todayWeatherData.getName() + " сегодня "+ System.lineSeparator() +
"Температура: " + String.format("%.1f", todayWeatherData.getTemp().getTemp()) + "°C, " + System.lineSeparator()+
"Влажность: " + todayWeatherData.getTemp().getHumidity() + "%, " + System.lineSeparator()+
"Осадки: " + todayWeatherData.getWeatherToday().get(0).getDescription()+ System.lineSeparator()+
"Скорость ветра: " + (int)todayWeatherData.getWind().getSpeed() + " м/с" + System.lineSeparator()+
"http://openweathermap.org/img/w/" + todayWeatherData.getWeatherToday().get(0).getIcon() + ".png");
return "В городе: " + todayWeatherData.getName() + " сегодня "+ System.lineSeparator() +
"Температура: " + String.format("%.1f", todayWeatherData.getTemp().getTemp()) + "°C, " + System.lineSeparator()+
"Влажность: " + todayWeatherData.getTemp().getHumidity() + "%, " + System.lineSeparator()+
"Осадки: " + todayWeatherData.getWeatherToday().get(0).getDescription() + System.lineSeparator()+
"Скорость ветра: " + (int)todayWeatherData.getWind().getSpeed() + " м/с" + System.lineSeparator()+
"http://openweathermap.org/img/w/" + todayWeatherData.getWeatherToday().get(0).getIcon() + ".png";
}
}
Как я понял, необходимо сделать, чтобы в классе Weather запросы к серверу погоды шли в отдельном потоке. Вот цитата из задания к боту: "Стоит заметить, что обращения к OpenWeatherMap должны происходить в отдельном потоке". У меня своими силами реализовать не получается.
вот такая замена выполнит запрос в другом потоке (лучше использовать специально предназначенные для этого конструкции):
скорее всего, запрос на сайт отправляется в этой строке:
todayWeatherData = todayWeatherGson.fromJson(reader, OneDayWeather.class);
заменить ее на:
//todayWeatherData уже объявлена
Thread th = new Thread(
()->{
todayWeatherData = todayWeatherGson.fromJson(reader, OneDayWeather.class);
}
);
//запуск потока
th.Start();
//ожидание его завершения (текущий поток засыпает до окончания th)
th.Join();
P.S. думаю задание сформировано неверно. запрашивать асинхронно с сайта ничего само по себе не даст - тут мы ожидаем завершения потока
Есть такая штука как "Друлз": у него есть веб-приложение, позволяющее писать бизнес-правила прямо в браузере - называется "Business Central Workbench"