Spring: задача @Scheduled запускается через @Controller и Websocket

У меня есть задача @Scheduled, которая каждую секунду отправляет данные клиенту через веб-сокет.

Мне нужно запустить мою запланированную задачу только тогда, когда клиент попросит об этом.

Вместо этого моя задача запускается при запуске моего сервера. это не то поведение, которое я хочу.

в настоящее время у меня есть компонент моей запланированной задачи, который объявлен в моем SchedulingConfigurer:

@Configuration
@EnableScheduling
public class SchedulingConfigurer implements org.springframework.scheduling.annotation.SchedulingConfigurer {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        return new ThreadPoolTaskScheduler();
    }

    @Bean
    public ScheduledTask scheduledTask() {
        return new ScheduledTask();
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setTaskScheduler(taskScheduler());
    }

}

Вот мой код контроллера Spring:

@MessageMapping("/hello")
public void greeting() throws Exception {
   //How do I start my scheduled task here ?
}

Может быть, это невозможно сделать с аннотацией @Scheduled, и мне нужно использовать интерфейс TaskScheduler?


person stephane06    schedule 02.06.2014    source источник
comment
быстрый вопрос: не могли бы вы объяснить, почему вы не делаете это наоборот, то есть отправляете сообщения с запланированной задачей и позволяете клиенту подписываться на эту тему только при необходимости? Как в github.com/rstoyanchev/spring-websocket-portfolio?   -  person Brian Clozel    schedule 02.06.2014
comment
Я не хочу, чтобы задача выполнялась на сервере, если это нужно любому клиенту.   -  person stephane06    schedule 03.06.2014


Ответы (2)


  1. удалить объявление @Scheduled из класса ScheduledTask
  2. реализует интерфейс Runnable вместо

    @Component
    //@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class ScheduledTask implements Runnable {
    
        private static final Logger log = LoggerFactory.getLogger(ScheduledTask.class);
        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
    
        public void doWork() {
            printMessage();
            // TODO real work
        }
    
        private void printMessage() {
            log.info("time to work: {}", dateFormat.format(new Date()));
        }
    
        @Override
        public void run() {
            doWork();
        }
    }
    
  3. запланируйте свою задачу в области контроллера, как это

    @Controller
    public class ScheduledTaskController {
    
      @Autowired
      private TaskScheduler taskScheduler;
    
      @Autowired
      private ScheduledTask scheduledTask;
    
      @RequestMapping(value = "/task/run", method = RequestMethod.GET)
      public String runTask() {
        // start to run task every 5 sec.
        taskScheduler.schedule(scheduledTask, new CronTrigger("0/5 * * * * ?"));
    
        // ok, redirect
        return "redirect:/task";
      }
    }
    
person cane    schedule 17.05.2016
comment
Отличный ответ. Я потратил целый день на поиски этого. - person madcoderz; 14.05.2019

@Schedule - это декларативный способ, поэтому это не то, чего вы пытаетесь достичь здесь.

Вы можете создать Бин, используя одну из реализаций TaskScheduler, например ThreadPoolTaskScheduler и добавьте этот компонент в свое приложение. Он имеет все необходимые методы для динамического планирования задач.

person Brian Clozel    schedule 03.06.2014