#java #spring #rest #spring-boot #resttemplate
#java #spring #rest #spring-boot #resttemplate
Вопрос:
Я пытаюсь создать приложение SpringBoot, которое будет использовать данные из стороннего REST API и отправлять уведомления Websocket моим собственным клиентам на основе событий / изменений в этих данных. Данные, которые я использую, часто меняются, иногда десятки раз в секунду (колебания цен на криптовалюту ведут себя аналогично этим данным). Я хочу повторно вызывать API с фиксированным интервалом (например, каждые 1-10 секунд), отслеживать определенные события / изменения и запускать Websocket push при возникновении этих событий.
Я смог создать простое приложение Spring Boot, которое может отправлять уведомления Websocket и использовать API, следуя этим руководствам:
Проблема: я могу заставить приложение запрашивать данные из API только один раз. Я потратил часы на поиск всех возможных вариантов «множественных / повторяющихся / постоянных вызовов Spring RestTemplate», но я не могу найти решение, которое учитывало бы мое конкретное использование. Самые близкие примеры, которые я нашел, используют повторные попытки, но даже они в конечном итоге заканчиваются неудачей. Я хочу, чтобы мое приложение постоянно запрашивало эти данные до тех пор, пока я не закрою приложение. Я знаю, что мог бы обернуть это в while(true)
инструкцию или что-то в этом роде, но это действительно не подходит для такой платформы, как SpringBoot, и все еще возникают проблемы при попытке создать экземпляр RestTemplate.
Как я могу реализовать постоянный запрос к ресурсу RESTful API?
Ниже приведено то, что у меня есть в моем классе приложений
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableScheduling
public class Application {
private static final String API_URL = "http://hostname.com/api/v1/endpoint";
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
RestTemplate restTemplate(RestTemplateBuilder builder){
return builder.build();
}
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
Response response= restTemplate.getForObject(API_URL, Response.class);
System.out.println(response.toString());
};
}
}
Комментарии:
1. Вам нужно изучить правильное использование
@Scheduled
аннотации. Кроме того,CommandLineRunner
выполняется ТОЛЬКО один раз, во время запуска приложения. Вам нужно прочитать еще немного о spring и его использовании.
Ответ №1:
CommandLineRunner
запускается только один раз при запуске приложения. Вместо этого вы хотите использовать @Scheduled
аннотацию для выполнения повторяющихся операций с фиксированными интервалами, например
@Scheduled(fixedDelay = 1000L)
public void checkApi() {
Response response = restTemplate.getForObject(API_URL, Response.class);
System.out.println(response.toString())
}
Это не обязательно должно быть Bean
, это может быть просто простой метод. Смотрите руководство Spring для получения дополнительной информации https://spring.io/guides/gs/scheduling-tasks /
Ответ №2:
Добавьте @EnableScheduling
аннотацию к вашему классу SpringConfig или основному классу.
Вы можете использовать запланированную фиксированную задержку или фиксированную скорость
@Scheduled(fixedDelay = 10000)
public void test() {
System.out.println("Scheduler called.");
}
или
@Scheduled(fixedRate = 10000)
public void test() {
System.out.println("Scheduler called.");
}
Разница между fixedDelay и fixedRate:
fixedDelay — проверяет, существует ли задержка в n миллисекунд между временем завершения выполнения задачи и временем начала следующего выполнения задачи.
fixedRate — запускает запланированную задачу каждые n миллисекунд.
В идеале, вы также должны экстернализировать значение fixedDelay или fixedRate в файле application.properties:
@Scheduled(fixedDelayString = "${scheduler.fixed.delay}")
public void test() {
System.out.println("Scheduler called.");
}
В вашем файле application.properties добавьте приведенную ниже конфигурацию:
scheduler.fixed.delay = 10000
Надеюсь, это поможет.