이 시나리오를 처리하는 한 가지 방법이 있습니다.
첫 번째 봄 구성에서는 SchedulerFactoryBean
을 지정하고 Scheduler
을 다른 빈에 삽입 할 수 있습니다.
<bean name="SchedulerFactory"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="applicationContextSchedulerContextKey">
<value>applicationContext</value>
</property>
</bean>
그런 다음 응용 프로그램에서 작업을 만들 때 데이터베이스에 작업의 세부 정보를 저장합니다. 이 서비스는 내 컨트롤러 중 하나 그리고 스케줄 작업에 의해 호출됩니다
이
@Component
public class FollowJobService {
@Autowired
private FollowJobRepository followJobRepository;
@Autowired
Scheduler scheduler;
@Autowired
ListableBeanFactory beanFactory;
@Autowired
JobSchedulerLocator locator;
public FollowJob findByClient(Client client){
return followJobRepository.findByClient(client);
}
public void saveAndSchedule(FollowJob job) {
job.setJobType(JobType.FOLLOW_JOB);
job.setCreatedDt(new Date());
job.setIsEnabled(true);
job.setIsCompleted(false);
JobContext context = new JobContext(beanFactory, scheduler, locator, job);
job.setQuartzGroup(context.getQuartzGroup());
job.setQuartzName(context.getQuartzName());
followJobRepository.save(job);
JobSchedulerUtil.schedule(new JobContext(beanFactory, scheduler, locator, job));
}
}
내가 빌드 할 JobContext
해당 작업에 대한 세부 사항을 포함하고 결국 스케줄링 작업을위한 유틸리티로 전달됩니다. 다음은 실제로 작업을 예약하는 유틸리티 메소드의 코드입니다. 내 서비스에서 나는 JobScheduler
을 autowire하고 JobContext
으로 전달합니다. 또한 저장소를 사용하여 데이터베이스에 작업을 저장합니다. 그래서이 모든 코드 후
/**
* Schedules a DATA_MINING_JOB for the client. The job will attempt to enter
* followers of the target into the database.
*/
@Override
public void schedule(JobContext context) {
Client client = context.getNetworkSociallyJob().getClient();
this.logScheduleAttempt(context, client);
JobDetail jobDetails = JobBuilder.newJob(this.getJobClass()).withIdentity(context.getQuartzName(), context.getQuartzGroup()).build();
jobDetails.getJobDataMap().put("job", context.getNetworkSociallyJob());
jobDetails.getJobDataMap().put("repositories", context.getRepositories());
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(context.getQuartzName() + "-trigger", context.getQuartzGroup())
.withSchedule(cronSchedule(this.getSchedule())).build();
try {
context.getScheduler().scheduleJob(jobDetails, trigger);
this.logSuccess(context, client);
} catch (SchedulerException e) {
this.logFailure(context, client);
e.printStackTrace();
}
}
내 작업은 데이터베이스에 저장하고 그는 석영 스케줄러를 사용하여 예약 된, 내가 두 가지 일이 일어날 실행합니다. 이제 응용 프로그램이 다시 시작되면 스케줄러로 작업을 다시 예약하려고합니다. 이를 위해 콘테이너가 재시작되거나 시작될 때마다 스프링에 의해 호출되는 ApplicationListener<ContextRefreshedEvent>
을 구현하는 빈을 등록한다.
<bean id="jobInitializer" class="com.network.socially.web.jobs.JobInitializer"/>
JobInitializer.class
public class JobInitializer implements ApplicationListener<ContextRefreshedEvent> {
Logger logger = LoggerFactory.getLogger(JobInitializer.class);
@Autowired
DataMiningJobRepository repository;
@Autowired
ApplicationJobRepository jobRepository;
@Autowired
Scheduler scheduler;
@Autowired
JobSchedulerLocator locator;
@Autowired
ListableBeanFactory beanFactory;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
logger.info("Job Initilizer started.");
//TODO: Modify this call to only pull completed & enabled jobs
for (ApplicationJob applicationJob : jobRepository.findAll()) {
if (applicationJob.getIsEnabled() && (applicationJob.getIsCompleted() == null || !applicationJob.getIsCompleted())) {
JobSchedulerUtil.schedule(new JobContext(beanFactory, scheduler, locator, applicationJob));
}
}
}
}
이 클래스는 스케줄러와 ApplicationJob
인터페이스를 구현하는 내 작업의 각 인스턴스를 잡고 저장소를 autowires. 이 데이터베이스 레코드의 정보를 사용하여 스케줄러 유틸리티를 사용하여 작업을 재구성 할 수 있습니다.
그래서 기본적으로 데이터베이스에 작업을 수동으로 저장하고 적절한 빈에 Scheduler
의 인스턴스를 주입하여 수동으로 작업을 예약합니다. 다시 일정을 잡으려면 데이터베이스에 쿼리 한 다음 ApplicationListener
을 사용하여 컨테이너를 다시 시작하고 시작하는 시간을 고려하여 일정을 예약합니다.
웹 응용 프로그램? –
예, 내 프로젝트가 웹 응용 프로그램입니다. – davioooh
작업이 시작시 호출되도록 구성되었는지 확인하기 위해 속성을 읽었을 것입니다. 서버를 다시 시작하는 동안 컨텍스트가로드되므로이 속성을 읽고 작업을 시작합니다. –