详解SpringBoot 创建定时任务(配合数据库动态执行)

先来介绍一下 SpringBoot 这个框架。SpringBoot 是一款基于 Spring 框架的快速开发框架,能够帮助开发者快速搭建 Spring 应用,极大地提高了开发效率。在 SpringBoot 中,我们可以非常简单地创建定时任务并进行动态执行,下面是详解 SpringBoot 创建定时任务(配合数据库动态执行)的攻略:

一、引入相关依赖

在创建我们的 SpringBoot 项目时,需要在 pom.xml 中加上以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.3.0</version>
</dependency>

其中,spring-boot-starter-data-jdbc 是 SpringBoot 自带的 JDBC 数据库框架,spring-boot-starter-quartz 是帮助我们管理定时任务的框架,quartz-jobs 是 Quartz 任务调度框架的依赖。

二、编写定时任务

下面为一个简单的固定执行时间的定时任务,代码如下:

@Component
public class HelloJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Hello World!");
    }
}

@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail helloJobDetail() {
        return JobBuilder.newJob(HelloJob.class).withIdentity("helloJob").storeDurably().build();
    }

    @Bean
    public Trigger helloJobTrigger() {
        return TriggerBuilder.newTrigger().forJob(helloJobDetail()).withIdentity("helloJobTrigger")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setJobDetails(helloJobDetail());
        factory.setTriggers(helloJobTrigger());
        return factory;
    }
}

HelloJob 实现了 Quartz 的 Job 接口,我们可以在 execute 方法中编写我们的业务逻辑。QuartzConfig 配置类中定义了 helloJobDetail 和 helloJobTrigger 两个 Bean,用于定义 Job 和 Trigger 的具体信息,并指定在何时执行。同时,我们在 schedulerFactoryBean 中通过设置 JobDetails 和 Triggers 来将 Job 和 Trigger 关联起来。在 Cron 表达式中设置定时任务执行时间,这里我们设置的是每 5 秒执行一次。

在以上代码中,我们使用了 Quartz 的 CronScheduleBuilder 类来设置定时任务的执行时间,以下是几个常用的 Cron 表达式:

  • "0/5 * * * * ?":每 5 秒执行一次
  • "0 0 12 * * ?":每天中午 12 点执行
  • "0 15 10 ? * *":每天上午 10:15 执行
  • "0 15 10 * * ?":每天上午 10:15 执行
  • "0 15 10 * * ? *":每天上午 10:15 执行
  • "0 15 10 * * ? 2019":2019 年的每天上午 10:15 执行

三、动态执行任务

接下来,我们将了解如何从数据库中动态获取任务定时时间并执行任务。

首先,我们需要定义一个接口,用于定义定时任务的服务方法:

public interface ScheduledTaskService {
    /**
     * 获取所有的数据库中的定时任务
     * @return
     */
    List<ScheduledTask> getAllScheduledTask();

    /**
     * 根据定时任务 ID 执行定时任务
     * @param scheduledTaskId
     */
    void executeTask(Integer scheduledTaskId);
}

ScheduledTaskService 接口中定义了 getAllScheduledTask 和 executeTask 两个方法,用于获取数据库中的定时任务和执行定时任务,具体实现方式如下:

@Service
public class ScheduledTaskServiceImpl implements ScheduledTaskService {

    @Autowired
    private ScheduledTaskDao scheduledTaskDao;

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Override
    public List<ScheduledTask> getAllScheduledTask() {
        return scheduledTaskDao.getAllScheduledTask();
    }

    @Override
    public void executeTask(Integer scheduledTaskId) {
        Optional<ScheduledTask> optionalScheduledTask = scheduledTaskDao.getScheduledTaskById(scheduledTaskId);
        if (optionalScheduledTask.isPresent()) {
            ScheduledTask scheduledTask = optionalScheduledTask.get();
            String cronExpression = scheduledTask.getCronExpression();
            JobDetail jobDetail = JobBuilder.newJob(ScheduledTaskJob.class)
                                            .withIdentity(scheduledTask.getJobName(), scheduledTask.getJobGroup())
                                            .storeDurably()
                                            .build();
            jobDetail.getJobDataMap().put("scheduledTaskId", scheduledTaskId);
            Trigger trigger = TriggerBuilder.newTrigger()
                                             .forJob(jobDetail)
                                             .withIdentity(scheduledTask.getTriggerName(), scheduledTask.getTriggerGroup())
                                             .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
                                             .build();
            try {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                scheduler.addJob(jobDetail, true, true);
                scheduler.scheduleJob(trigger);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    }
}

ScheduledTaskServiceImpl 中使用了 ScheduledTaskDao 中定义的方法来获取数据库中的任务信息,然后通过 JobBuilder 和 TriggerBuilder 对任务和触发器进行构建,并且将任务和触发器关联,将任务存入调度中心并且执行。

另外,我们还需要定义一个 Job,用于执行定时任务。以下是该 Job 的具体实现:

@Service
public class ScheduledTaskJob implements Job {

    @Autowired
    private ScheduledTaskDao scheduledTaskDao;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDataMap dataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        Integer scheduledTaskId = (Integer) dataMap.get("scheduledTaskId");
        Optional<ScheduledTask> optionalScheduledTask = scheduledTaskDao.getScheduledTaskById(scheduledTaskId);
        if (optionalScheduledTask.isPresent()) {
            ScheduledTask scheduledTask = optionalScheduledTask.get();
            // TODO 执行具体的任务逻辑
            System.out.println(new Date() + "执行定时任务:" + scheduledTask.getTaskName());
        }
    }
}

ScheduledTaskJob 中实现了 Quartz 的 Job 接口,并且通过 ScheduledTaskDao 从数据库中获取任务信息,然后执行具体的业务逻辑。该 Job 中的任务逻辑可以是任何我们想要执行的具体业务逻辑,比如发送邮件、统计数据、备份数据等等。

最后,我们需要定义一个存放定时任务信息的实体类 ScheduledTask:

public class ScheduledTask {

    private Integer scheduledTaskId;

    private String taskName;

    private String jobName;

    private String jobGroup;

    private String triggerName;

    private String triggerGroup;

    private String cronExpression;

    // 省略 getter 和 setter 方法
}

ScheduledTask 类中定义了任务的各项属性,包括任务 ID、任务名称、Job 名称、Job 组、Trigger 名称、Trigger 组以及任务的 Cron 表达式等。

示例讲解

接下来,我们来看两个示例,分别用于演示如何创建并执行定时任务。

首先,我们来创建一个每分钟执行一次的任务。

  1. 假设我们已经在数据库中创建好了一条定时任务信息:

scheduled_task_id:1

task_name:每分钟执行一次的任务

job_name:job1

job_group:group1

trigger_name:trigger1

trigger_group:group1

cron_expression:0 0/1 * * * ?

@Component
public class EveryMinuteJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("This is a job which will be executed every minute.");
    }
}

@Configuration
public class QuartzConfig {
    @Bean(name = "everyMinuteJobDetail")
    public JobDetail everyMinuteJobDetail() {
        return JobBuilder.newJob(EveryMinuteJob.class).withIdentity("job1", "group1").storeDurably().build();
    }

    @Bean(name = "everyMinuteJobTrigger")
    public Trigger everyMinuteJobTrigger() {
        return TriggerBuilder.newTrigger().forJob(everyMinuteJobDetail()).withIdentity("trigger1", "group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0/1 * * * ?")).build();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setJobDetails(everyMinuteJobDetail());
        factory.setTriggers(everyMinuteJobTrigger());
        return factory;
    }
}
  1. 然后,我们在 ScheduledTaskServiceImpl 中创建一个方法,并调用 executeTask 方法来执行该定时任务:
@Service
public class ScheduledTaskServiceImpl implements ScheduledTaskService {

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Override
    public List<ScheduledTask> getAllScheduledTask() {
        return scheduledTaskDao.getAllScheduledTask();
    }

    @Override
    public void executeTask(Integer scheduledTaskId) {
        Optional<ScheduledTask> optionalScheduledTask = scheduledTaskDao.getScheduledTaskById(scheduledTaskId);
        if (optionalScheduledTask.isPresent()) {
            ScheduledTask scheduledTask = optionalScheduledTask.get();
            String cronExpression = scheduledTask.getCronExpression();
            JobDetail jobDetail = JobBuilder.newJob(EveryMinuteJob.class)
                                            .withIdentity(scheduledTask.getJobName(), scheduledTask.getJobGroup())
                                            .storeDurably()
                                            .build();
            Trigger trigger = TriggerBuilder.newTrigger()
                                             .forJob(jobDetail)
                                             .withIdentity(scheduledTask.getTriggerName(), scheduledTask.getTriggerGroup())
                                             .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
                                             .build();
            try {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                scheduler.addJob(jobDetail, true, true);
                scheduler.scheduleJob(trigger);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    }
}
  1. 最后,我们可以在 controller 中调用 executeTask 方法来执行该定时任务:
@RestController
@RequestMapping("/scheduledTask")
public class ScheduledTaskController {

    @Autowired
    private ScheduledTaskService scheduledTaskService;

    @RequestMapping("/execute")
    public String executeScheduledTask() {
        scheduledTaskService.executeTask(1);
        return "execute success.";
    }
}

现在,我们来创建一个每天 10:15 执行一次的任务。

  1. 假设我们已经在数据库中创建好了一条定时任务信息:

scheduled_task_id:2

task_name:每天 10:15 执行一次的任务

job_name:job2

job_group:group2

trigger_name:trigger2

trigger_group:group2

cron_expression:0 15 10 ? * *

@Component
public class EveryDayJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("This is a job which will be executed every day at 10:15.");
    }
}

@Configuration
public class QuartzConfig {
    @Bean(name = "everyDayJobDetail")
    public JobDetail everyDayJobDetail() {
        return JobBuilder.newJob(EveryDayJob.class).withIdentity("job2", "group2").storeDurably().build();
    }

    @Bean(name = "everyDayJobTrigger")
    public Trigger everyDayJobTrigger() {
        return TriggerBuilder.newTrigger().forJob(everyDayJobDetail()).withIdentity("trigger2", "group2")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 15 10 ? * *")).build();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setJobDetails(everyDayJobDetail());
        factory.setTriggers(everyDayJobTrigger());
        return factory;
    }
}
  1. 然后,我们在 ScheduledTaskServiceImpl 中创建一个方法,并调用 executeTask 方法来执行该定时任务:
@Service
public class ScheduledTaskServiceImpl implements ScheduledTaskService {

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Override
    public List<ScheduledTask> getAllScheduledTask() {
        return scheduledTaskDao.getAllScheduledTask();
    }

    @Override
    public void executeTask(Integer scheduledTaskId) {
        Optional<ScheduledTask> optionalScheduledTask = scheduledTaskDao.getScheduledTaskById(scheduledTaskId);
        if (optionalScheduledTask.isPresent()) {
            ScheduledTask scheduledTask = optionalScheduledTask.get();
            String cronExpression = scheduledTask.getCronExpression();
            JobDetail jobDetail = JobBuilder.newJob(EveryDayJob.class)
                                            .withIdentity(scheduledTask.getJobName(), scheduledTask.getJobGroup())
                                            .storeDurably()
                                            .build();
            Trigger trigger = TriggerBuilder.newTrigger()
                                             .forJob(jobDetail)
                                             .withIdentity(scheduledTask.getTriggerName(), scheduledTask.getTriggerGroup())
                                             .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
                                             .build();
            try {
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                scheduler.addJob(jobDetail, true, true);
                scheduler.scheduleJob(trigger);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    }
}
  1. 最后,我们可以在 controller 中调用 executeTask 方法来执行该定时任务:
@RestController
@RequestMapping("/scheduledTask")
public class ScheduledTaskController {

    @Autowired
    private ScheduledTaskService scheduledTaskService;

    @RequestMapping("/execute")
    public String executeScheduledTask() {
        scheduledTaskService.executeTask(2);
        return "execute success.";
    }
}

至此,我们已经通过 SpringBoot 框架实现了动态创建并执行定时任务的功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解SpringBoot 创建定时任务(配合数据库动态执行) - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 使用JDBC连接Mysql数据库会出现的问题总结

    使用JDBC连接Mysql数据库会出现的问题总结 JDBC是Java针对各种关系型数据库提供的一种标准的接口,可以大大简化Java程序连接数据库的开发工作。但是,在使用JDBC连接Mysql数据库的过程中,常常会遇到一些问题。本篇攻略将会针对常见的问题进行总结,并给出相应的解决方案。 1. ClassNotFoundException 该异常通常在程序中出现…

    Java 2023年5月20日
    00
  • java JSON解析库Alibaba Fastjson用法详解

    Java JSON解析库Alibaba Fastjson用法详解 JSON作为一种轻量级的数据交换格式,被广泛应用于各种应用中。而Alibaba Fastjson作为一个性能优越、使用简单的JSON解析库,受到了开发者的喜爱。本文将详细讲解Fastjson的使用方法。 前置知识 在使用Fastjson之前,需要了解一些相关的知识: JSON格式(了解其基本结…

    Java 2023年5月26日
    00
  • linux负载均衡总结性说明 四层负载和七层负载有什么区别

    什么是负载均衡 负载均衡 (Load Balancing)是一种通过将任务或工作负载分配到多个计算机、服务器、网络接口或磁盘驱动器上实现的计算机网络技术。负载均衡旨在通过在不同的计算机系统之间平均分配工作负载,从而实现更高的性能、更快的响应时间、更高的可用性和更高的可扩展性。 四层负载均衡和七层负载均衡的区别 四层负载均衡和七层负载均衡是两种常见的负载均衡技…

    Java 2023年5月20日
    00
  • Spring Security 实现多种登录方式(常规方式外的邮件、手机验证码登录)

    下面是 Spring Security 实现多种登录方式的完整攻略: 概述 Spring Security 是 Spring 生态中的一个安全框架,它提供了许多安全方面的功能,如认证、授权和攻击防护等。其中认证功能就是判断用户是否合法,并确定用户是否具有相关资源的访问权限。 常规方式的登录是通过用户名和密码进行认证,而本文要讨论的是除常规方式外的邮件、手机验…

    Java 2023年5月20日
    00
  • 教你利用SpringBoot写一个属于自己的Starter

    教你利用SpringBoot写一个属于自己的Starter Spring Boot Starter是一种用于简化Spring应用程序配置的机制。它可以将一组相关的依赖项打包到一个单独的模块中,并提供自动配置和其他功能。本文将详细介绍如何编写一个属于自己的Spring Boot Starter,并提供两个示例。 创建Starter项目 首先,我们需要创建一个M…

    Java 2023年5月15日
    00
  • Java调用SQL脚本执行常用的方法示例

    Java调用SQL脚本执行常用的方法示例有很多种,下面我分别给出两种示例和详细攻略。 示例一 需求描述 我们需要在Java应用中执行一些SQL脚本文件,以便初始化数据库。这些脚本文件需要在应用启动时执行,只需要执行一次。 实现步骤 将SQL脚本文件包含在Java应用的classpath中,例如存放在/src/main/resources/sql目录下。 使用…

    Java 2023年5月20日
    00
  • jsp倒计时简单实现方法

    关于 “jsp倒计时简单实现方法” ,我可以提供以下详细的攻略: 一、前置知识 在实现倒计时的过程中,需要了解基本的前端技术(如html、css、JavaScript)和后端技术(如jsp等),并且需要了解 Javascript 定时器的使用方法。 二、实现步骤 创建一个jsp页面,实现基本的页面布局(比如可以放置一个计时器 div 容器)。 在页面中加入J…

    Java 2023年6月15日
    00
  • Maven 多模块父子工程的实现(含Spring Boot示例)

    首先,需要了解什么是 Maven 多模块工程。Maven 是一款构建工具,对于大型项目来说,通常需要拆分为多个模块来管理,这些模块之间可能存在依赖关系,这时候就可以使用 Maven 的多模块工程来管理这些模块。 Maven 多模块工程通常会分为两种类型:聚合项目和继承项目。聚合项目指的是父项目与子项目并列存在于同一级目录下,而继承项目则指的是父项目和子项目分…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部