Je définis des travaux planifiés avec des modèles de style cron au printemps, en utilisant le @Scheduled
annotation.
Le modèle cron est stocké dans un fichier de propriétés de configuration. En réalité, il existe deux fichiers de propriétés: une configuration par défaut et une configuration de profil qui dépend de l'environnement (par exemple, dev, test, client prod 1, client prod 2, etc.) et remplace certaines des valeurs par défaut.
J'ai configuré un bean espace réservé de propriété dans mon contexte de printemps, ce qui me permet d'utiliser ${}
espaces réservés de style pour importer les valeurs de mes fichiers de propriétés.
Le job beans ressemble à ceci:
@Component
public class ImagesPurgeJob implements Job {
private Logger logger = Logger.getLogger(this.getClass());
@Override
@Transactional(readOnly=true)
@Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
public void execute() {
//Do something
//can use DAO or other autowired beans here
}
}
Parties pertinentes de mon contexte XML:
<!-- Enable configuration of scheduled tasks via annotations -->
<task:annotation-driven/>
<!-- Load configuration files and allow '${}' style placeholders -->
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config/default-config.properties</value>
<value>classpath:config/environment-config.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="ignoreResourceNotFound" value="false"/>
</bean>
J'aime vraiment ça. C'est assez simple et propre avec un minimum de XML.
Cependant, j'ai une autre exigence: certains de ces emplois peuvent être totalement handicapés dans certains cas.
Donc, avant d’utiliser Spring pour les gérer, je les ai créés manuellement et il existe un paramètre booléen ainsi que le paramètre cron dans les fichiers de configuration, pour spécifier si le travail doit être activé ou non:
jobs.mediafiles.imagesPurgeJob.enable=true or false
jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?
Comment puis-je utiliser ce paramètre dans Spring pour créer de manière conditionnelle ou simplement ignorer le bean, en fonction de ce paramètre de configuration?
Une solution évidente serait de définir un modèle cron qui ne serait jamais évalué, afin que le travail ne soit jamais exécuté. Mais le haricot serait toujours créé et la configuration serait un peu obscure, donc je pense qu'il doit y avoir une meilleure solution.
@Component
public class ImagesPurgeJob implements Job {
private Logger logger = Logger.getLogger(this.getClass());
@Value("${jobs.mediafiles.imagesPurgeJob.enable}")
private boolean imagesPurgeJobEnable;
@Override
@Transactional(readOnly=true)
@Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
public void execute() {
//Do something
//can use DAO or other autowired beans here
if(imagesPurgeJobEnable){
Do your conditional job here...
}
}
}
Spring Boot fournit @ ConditionalOnProperty , ce qui serait parfait si vous utilisiez Spring Boot. Cette annotation est une spécialisation de @ Conditionnel , introduite avec Spring 4.0.0.
En supposant que vous utilisiez uniquement des sources "normales" et non Spring Boot, vous pouvez créer votre propre implémentation de condition à utiliser avec @Conditional qui imiterait @ConditionalOnProperty de Spring Boot.
Vous pouvez regrouper les méthodes de planification par conditions en nombre de services et les initier de la manière suivante:
@Service
@ConditionalOnProperty("yourConditionPropery")
public class SchedulingService {
@Scheduled
public void task1() {...}
@Scheduled
public void task2() {...}
}
Si vous souhaitez basculer @EnableScheduling d'une propriété, vous pouvez le faire dans Spring Boot en déplaçant l'annotation @EnableScheduling vers une classe de configuration et en utilisant @ConditionalOnProperty comme suit:
@Configuration
@EnableScheduling
@ConditionalOnProperty(prefix = "com.example.scheduling", name="enabled", havingValue="true", matchIfMissing = true)
public class SchedulingConfiguration {
}
Cela désactivera la planification pour l'application. Cela peut être utile dans une situation où vous souhaitez pouvoir exécuter l'application une fois ou planifiée en fonction de la manière dont elle est démarrée.
Du commentaire de Wilkinsona sur ici: https://github.com/spring-projects/spring-boot/issues/12682
Votre question dit de conditionner la création réelle du haricot. Vous pouvez le faire facilement avec ce paramètre en utilisant @Profile si vous utilisez au moins Spring 3.1.
Voir la documentation ici: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html
@Component
public class CurrencySyncServiceImpl implements CurrencySyncService {
private static Boolean isEnableSync;
/**
* Currency Sync FixedDelay in minutes
*/
private static Integer fixedDelay;
@Transactional
@Override
@Scheduled(fixedDelayString = "#{${currency.sync.fixedDelay}*60*1000}")
public void sync() {
if(CurrencySyncServiceImpl.isEnableSync) {
//Do something
//you can use DAO or other autowired beans here.
}
}
@Value("${currency.sync.fixedDelay}")
public void setFixedDelay(Integer fixedDelay) {
CurrencySyncServiceImpl.fixedDelay = fixedDelay;
}
@Value("${currency.sync.isEnable}")
public void setIsEnableSync(Boolean isEnableSync) {
CurrencySyncServiceImpl.isEnableSync = isEnableSync;
}
}
Vous pouvez également créer un bean basé sur une condition et ce bean peut avoir une méthode planifiée.
@Component
@Configuration
@EnableScheduling
public class CustomCronComponent {
@Bean
@ConditionalOnProperty(value = "my.cron.enabled", matchIfMissing = true, havingValue = "true")
public MyCronTask runMyCronTask() {
return new MyCronTask();
}
}
et
@Component
public class MyCronTask {
@Scheduled(cron = "${my.cron.expression}")
public void run() {
String a = "";
}
}
Je sais que ma réponse est un hack, mais donner une expression cron valide qui ne s’exécute jamais peut résoudre le problème (dans la configuration spécifique à l’environnement), Quartz: expression Cron qui ne s’exécutera jamais