2016-08-31 6 views
3

Я хочу сделать что-то вроде javascript's setInterval(function, interval)/setTimeout(function, timeout) в Spring Boot.Весенняя ботинок - альтернатива расписанию времени.

Я нашел @Scheduled аннотацию, которая имеет fixedRate аргумент, но как аннотацию я не могу изменить скорость динамически (или я могу?)

Сейчас я использую java.util.Timer, но я предпочел бы использовать Spring. Есть ли способ?

Могу ли я получить экземпляр Scheduler и работать с ним динамически?

спасибо!

ответ

0

Нашли решение, которое подходит для моего дела.

В Main.java:

@SpringBootApplication 
@ConfigurationProperties 
@EnableScheduling 
public class Main { 
    @Bean 
    ThreadPoolTaskScheduler taskScheduler() { 
     return new ThreadPoolTaskScheduler(); 
    } 

    public static void main(String[] args) { 
     SpringApplication.run(Main.class, args); 
    } 
} 

В службе.java (Вызывается из контроллера отдыха):

@Service 
public class Service { 
    private static final Logger log = LoggerFactory.getLogger(Service.class); 
    private final TaskScheduler scheduler; 

    @Autowired 
    public Service(TaskScheduler scheduler) { 
     this.scheduler = scheduler; 
    } 

    public void startTask(int inteval) { 
     scheduler.schedule(() -> log.info("Doing work"), triggerContext -> { 
      if (some_condition) { 
       ZonedDateTime now = ZonedDateTime.now(); 

       return Date.from(now.plusSeconds(interval).toInstant()); 
      } else { 
       // Stop the execution 
       return null; 
      } 
     }); 
    } 
} 

Это решение работает, но я не уверен, что это правильный путь.

Пожалуйста, можете прокомментировать ниже, и я могу изменить решение, если я получу предложение, которое я нахожу полезным.

2

Вы можете использовать Trigger, который позволяет динамически контролировать следующее выполнение. Вы должны реализовать SchedulingConfigurer, другой ответ охватывает именно это:

Scheduling a job with Spring programmatically (with fixedRate set dynamically)

EDIT, чтобы ответить на комментарии:

nextExecutionTime называется и дальше и дальше ... В следующий раз, когда задачи (и nextExecutionTime) называются определяется следующим образом:

nextExecutionTime.setTime(lastActualExecutionTime != null ? lastActualExecutionTime : new Date()); 
nextExecutionTime.add(Calendar.MILLISECOND, numberOfMillisecondsBeforeCallingTheTask); 

Все, что вам нужно сделать, это иметь это numberOfMillisecondsBeforeCallingTheTask значение чанга редактор

Пример:

@RestController 
public class MyController { 

    public static int triggerDelay = 1000; 

    @RequestMapping("/changetrigger/{val}") 
    public void test(@PathVariable int val){ 
     this.triggerDelay = val; 
    } 
} 
@SpringBootApplication 
@EnableScheduling 
public class Launcher implements SchedulingConfigurer{ 

    public static void main(String[] args){ 
     new SpringApplicationBuilder() // 
     .sources(Launcher.class)// 
     .run(args); 
    } 

    @Bean(destroyMethod = "shutdown") 
    public Executor taskExecutor() { 
     return Executors.newScheduledThreadPool(100); 
    } 

    @Override 
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { 
     taskRegistrar.setScheduler(taskExecutor()); 
     ; 
     taskRegistrar.addTriggerTask(new TriggerTask(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("blah"); 
       System.out.println(System.currentTimeMillis()); 
      } 
     }, new Trigger() { 
      @Override 
      public Date nextExecutionTime(TriggerContext triggerContext) { 
       Calendar nextExecutionTime = new GregorianCalendar(); 
       nextExecutionTime.setTime(new Date()); 
       nextExecutionTime.add(Calendar.MILLISECOND, MyController.triggerDelay); 
       System.out.println(System.currentTimeMillis()); 
       return nextExecutionTime.getTime(); 
      }})); 
    } 
} 

Обратите внимание, как динамическое значение MyController.triggerDelay используется для следующего выполнения. Поэтому, если вы измените номер, будет изменено следующее время выполнения. Вы увидите, поставили ли вы точку останова внутри nextExecutionTime.

+0

Выглядит хорошо, но работает только при запуске приложения, не так ли? Мне нужно постоянно запускать и останавливать запланированные задачи. –

+0

обновил ответ, чтобы объяснить, почему он динамичен. – alexbt

+0

Я нашел решение благодаря вам, но это немного другое. вероятно, больше подходит для моих нужд. Я проголосовал, и я добавлю свое собственное решение, чтобы получить некоторые отзывы об этом. Благодаря! –

0

Вы можете использовать @Scheduled(fixedRateString = "${spring.boot.schedule.rate}") для случая, когда spring.boot.schedule.rate является внешними свойствами в application.properties

spring.boot.schedule.rate = 5000

неправильно понял вопрос, выше только экстернализацию свойства ,

Для динамического решения, может быть, это должно быть работой, используя SPEL в annonation:

@Service 
public class ScheduledService { 
    @Autowired 
    private FixRateProperty fixRateProperty; 

    @Scheduled(fixedRateString = "#{fixRateProperty.fixRate}") 
    private void reportCurrentTime() { 
     System.out.println(new Date());; 
    } 
} 

Это FixRateProperty

@Component 
public class FixRateProperty { 
    private Long fixRate = 500L; 

    public Long getFixRate() { 
     return fixRate; 
    } 

    public void setFixRate(Long fixRate) { 
     this.fixRate = fixRate; 
    } 
} 

так что вы можете экстернализовать скорость в свойствах или установите fixRate.

+0

Это не динамическое решение. он определяется при запуске приложения и является глобальной константой. Если я хочу запускать несколько задач с разными расписаниями, это не сработает. –

+0

@ Algosub извините, я обновляю ответ, надеюсь, что это вам поможет. –

+0

Это все еще не то, что мне нужно. Пожалуйста, посмотрите на ответ, который я разместил, он может уточнить, что мне нужно. Я не знаю, хорошо ли мое решение, но оно работает для меня. Вы можете прокомментировать это, и я открыт для предложений. –

Смежные вопросы