今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

spring boot quartz定时任务

执行一个简单的任务

springboot中实现定时任务有多种方式,我们这里使用spring-boot-starter-quartz

引入依赖

compile group: 'org.springframework.boot', name: 'spring-boot-starter-quartz', version: '2.4.2'

 

定义一个job

public class CovidDaliyDataJob extends QuartzJobBean {

    @Autowired
    CovidService covidService;

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        covidService.saveDailyData();
    }
}

 

这里定时任务的内容为从新冠疫情数据统计网站获取每日的统计数据

 

@Component
public class CovidServiceImpl implements CovidService {
    Logger logger = LoggerFactory.getLogger(CovidServiceImpl.class);

    @Value("${covid.daily.data.api}")
    private String covidDaliyDataApi;
    @Autowired
    CovidRepository covidRepository;

    @Autowired
    RestTemplate restTemplate;

    @Override
    public void saveDailyData() {
        Covid[] dailyList= restTemplate.getForObject(covidDaliyDataApi,Covid[].class);
        logger.info("COVID daily data size ===>>>>>[{}]",dailyList.length);
    }
}

先将job存储类型配置为内存中。

spring.quartz.job-store-type=memory
covid.daily.data.api=https://api.covidtracking.com/v1/states/current.json

QuartzConfig配置

@Configuration
public class QuartzConfig {
 @Bean
    public JobDetail jobDetail() {
        return JobBuilder.newJob().ofType(CovidDaliyDataJob.class)
                .storeDurably()
                .withIdentity("Covid_Daily_Data_Job_Detail")
                .withDescription("获取每日的各个国家新冠病毒统计数据JobDetail")
                .build();
    }

    @Bean
    public Trigger trigger(JobDetail job) {
        return TriggerBuilder.newTrigger().forJob(job)
                .withIdentity("Covid_Daily_Data_Quartz_Trigger")
                .withDescription("获取每日的各个国家新冠病毒统计数据触发器")
                .withSchedule(simpleSchedule().repeatForever().withIntervalInSeconds(10))
                .build();
    }
}

因为springboot已经自动配置了SchedulerFactoryBean,我们可以不再配置Scheduler这样一个最简单的定时任务就可以执行了,为了便于测试这里设置10秒执行一次定时任务。

20:32:09.285 [quartzScheduler_Worker-6] DEBUG org.springframework.web.client.RestTemplate.debug - Accept=[application/json, application/*+json]
20:32:10.973 [quartzScheduler_Worker-6] DEBUG org.springframework.web.client.RestTemplate.debug - Response 200 OK
20:32:11.430 [quartzScheduler_Worker-6] DEBUG org.springframework.web.client.RestTemplate.debug - Reading to [com.example.springboot.model.Covid[]]
20:32:12.380 [quartzScheduler_Worker-6] INFO  com.example.springboot.service.impl.CovidServiceImpl.saveDailyData - COVID daily data size ===>>>>>[56]
20:32:19.293 [quartzScheduler_Worker-7] DEBUG org.springframework.web.client.RestTemplate.debug - HTTP GET https://api.covidtracking.com/v1/states/current.json
20:32:19.294 [quartzScheduler_Worker-7] DEBUG org.springframework.web.client.RestTemplate.debug - Accept=[application/json, application/*+json]
20:32:20.484 [quartzScheduler_Worker-7] DEBUG org.springframework.web.client.RestTemplate.debug - Response 200 OK
20:32:20.918 [quartzScheduler_Worker-7] DEBUG org.springframework.web.client.RestTemplate.debug - Reading to [com.example.springboot.model.Covid[]]
20:32:21.833 [quartzScheduler_Worker-7] INFO  com.example.springboot.service.impl.CovidServiceImpl.saveDailyData - COVID daily data size ===>>>>>[56]
20:32:29.293 [quartzScheduler_Worker-8] DEBUG org.springframework.web.client.RestTemplate.debug - HTTP GET https://api.covidtracking.com/v1/states/current.json
20:32:29.293 [quartzScheduler_Worker-8] DEBUG org.springframework.web.client.RestTemplate.debug - Accept=[application/json, application/*+json]
20:32:30.373 [quartzScheduler_Worker-8] DEBUG org.springframework.web.client.RestTemplate.debug - Response 200 OK
20:32:30.608 [quartzScheduler_Worker-8] DEBUG org.springframework.web.client.RestTemplate.debug - Reading to [com.example.springboot.model.Covid[]]
20:32:31.104 [quartzScheduler_Worker-8] INFO  com.example.springboot.service.impl.CovidServiceImpl.saveDailyData - COVID daily data size ===>>>>>[56]

从控制台可以看出定时任务已经执行了。

在上面的例子中,创建jobdetail和trriger也可以使用FactoryBean的形式

    @Bean
    public JobDetailFactoryBean jobDetail() {
        JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
        jobDetailFactory.setJobClass(CovidDaliyDataJob.class);
        jobDetailFactory.setName("Covid_Daily_Data_Job_Detail");
        jobDetailFactory.setDescription("获取每日的各个国家新冠病毒统计数据JobDetail");
        jobDetailFactory.setDurability(true);
        return jobDetailFactory;
    }
    @Bean
    public SimpleTriggerFactoryBean trigger(JobDetail job) {
        SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
        trigger.setJobDetail(job);
        trigger.setName("Covid_Daily_Data_Quartz_Trigger");
        trigger.setDescription("获取每日的各个国家新冠病毒统计数据触发器");
        trigger.setRepeatInterval(10);
        trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        return trigger;
    }

   //corn 表达式触发器
    @Bean
    public CronTriggerFactoryBean trigger(JobDetail job) {
        CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
        trigger.setJobDetail(job);
        trigger.setName("Covid_Daily_Data_Quartz_Trigger");
        trigger.setDescription("获取每日的各个国家新冠病毒统计数据触发器");
        trigger.setCronExpression("30 10 1 * * ?");
        return trigger;
    }

将任务信息存储到数据中

quartz 任务默认存在内存中,要存储到数据库中,只需要配置spring.quartz.job-store-type=jdbc,启动spring应用,因为我这里使用的spring data jpa 会自动创建响应的表,也可以自己手动创建

配置自定义调动工厂bean,连接不同的数据源

我们可能需要将定时任务的表单独放在一个schema中,这样我们可以单独配置个quartz数据源。配置quartz.properties,设置定时任务的其他一些属性

spring.quartz.jdbc.initialize-schema=always
spring.datasource.quartz.jdbc-url=jdbc:mysql://127.0.0.1:3306/zlennon?serverTimezone=UTC&useSSL=false
spring.datasource.quartz.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.quartz.username=root
spring.datasource.quartz.password=123456

    @Bean
    @QuartzDataSource
    @ConfigurationProperties(prefix = "spring.datasource.quartz")
    public DataSource quartzDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail job, DataSource quartzDataSource) {

        SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
        schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
        schedulerFactory.setJobFactory(new SpringBeanJobFactory());
        schedulerFactory.setJobDetails(job);
        schedulerFactory.setTriggers(trigger);
        schedulerFactory.setDataSource(quartzDataSource);
        return schedulerFactory;
    }

 

分享到:

专栏

类型标签

网站访问总量