Spring RestTemplate: как повторно проверять службу Restful API?

#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
  

Надеюсь, это поможет.