Spring boot 集成Quartz 实现定时任务动态管理服务端

调查了下用Spring boot集成Quartz来实现定时任务的动态管理,记下来备用。

主要使用 Spring boot、Quartz、Mybatis实现,其中Quartz任务在SqlServer数据库保存,业务数据库是Oracle。

需要实现数据源的动态管理,定时任务使用Spring IOC管理等功能。

创建Maven project

POM中依赖如下:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
</parent>
<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.boot.version>1.5.10.RELEASE</spring.boot.version>
        <spring.cloud.version>Edgware.SR2</spring.cloud.version>
        <java.version>1.8</java.version>
</properties> 
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Spring Boot Test 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- GSON -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <!-- 代码简化 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- 日志 Log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <!-- Log4j2 异步支持 -->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>3.3.6</version>
        </dependency>
        <!-- 使用 @ConfigurationProperties @Value 使用 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>        
        <!-- quartz -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.8</version>
        </dependency>
        <!--ojdbc -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0</version>
        </dependency>
        <!-- sqlserver -->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>sqljdbc4</artifactId>
            <version>4.0</version>
        </dependency>
        <!-- api document -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.2.2</version>
        </dependency>
        <!--junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                        <skip>true</skip>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
                <!-- 忽略Test包 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <skipTests>true</skipTests>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <mainClass>com.demo.service.job.JobManagerApplication</mainClass>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

上面需要注意的是ojdbc的jar需要手动安装到本地maven仓库。

配置Quartz
在SqlServer中创建Quartz需要的数据库和表,这里的建表语句可以自行到Quartz官网下载;
在src/main/resources下新建quartz.properties文件用来配置Quartz:
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
# 线程池配置
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
#任务持久化
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = qzDS
org.quartz.jobStore.misfireThreshold = 5000
org.quartz.dataSource.qzDS.driver =  com.microsoft.sqlserver.jdbc.SQLServerDriver
org.quartz.dataSource.qzDS.URL = jdbc:sqlserver://127.0.0.1;DatabaseName=QUARTZ_DB
org.quartz.dataSource.qzDS.user = 
org.quartz.dataSource.qzDS.password = 
org.quartz.dataSource.qzDS.maxConnections = 10
编写代码,使用配置文件中的配置,并且把定时任务交给Spring IOC处理

自定义任务工厂类,将定时任务交给Spring

@Component
public class QuartzJobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory autowireCapableBeanFactory;

    /**
     * @see org.springframework.scheduling.quartz.AdaptableJobFactory#createJobInstance(org.quartz.spi.TriggerFiredBundle)
     */
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object jobInstance = super.createJobInstance(bundle);
        // 实现Job的IOC管理
        autowireCapableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

配置定时任务调度器

@Configuration
public class SchedulerConfig {
    @Autowired
    private QuartzJobFactory jobFactory;

    /**
     * 定时任务初始化监听器
     * 
     * @Title: initListener
     */
    @Bean
    public QuartzInitializerListener initListener() {
        return new QuartzInitializerListener();
    }

    /**
     * 任务调度器
     * 
     * @Title: scheduler
     * @throws IOException
     */
    @Bean(name = "Scheduler")
    public Scheduler scheduler() throws IOException {
        return schedulerFactoryBean().getScheduler();
    }

    /**
     * 任务调度器工厂
     * 
     * @Title: schedulerFactoryBean
     * @throws IOException
     */
    @Bean(name = "SchedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setQuartzProperties(quartzProperties());
        factory.setOverwriteExistingJobs(true);
        factory.setStartupDelay(15);
        factory.setJobFactory(jobFactory);
        return factory;
    }

    /**
     * 读取定时任务配置
     * 
     * @Title: quartzProperties
     * @throws IOException
     */
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }
}
配置多数据源
定义application.properties
server.port = 8001
spring.application.name =job-manager
#business data source#
biz.datasource.type = com.alibaba.druid.pool.DruidDataSource
biz.datasource.url = jdbc:oracle:thin:@127.0.0.1:1521:orcl
biz.datasource.driver-class-name = oracle.jdbc.OracleDriver
biz.datasource.username = 
biz.datasource.password = 
#job data sources#
job.datasource.type = com.alibaba.druid.pool.DruidDataSource
job.datasource.url = jdbc:sqlserver://127.0.0.1;DatabaseName=QUARTZ_DB
job.datasource.driver-class-name = com.microsoft.sqlserver.jdbc.SQLServerDriver
job.datasource.username = 
job.datasource.password = 
#druid#
spring.druid.initialSize = 10
spring.druid.minIdle = 10
spring.druid.maxActive = 20
spring.druid.maxWait = 60000
spring.druid.maxOpenPreparedStatements = 50
spring.druid.validationQuery = select count(0) from dual
spring.druid.testWhileIdle = true
#Mybatis#
mybatis.mapper-locations = classpath:mapper/mybatis-sqlmap-*.xml
mybatis.type-aliases-package = com.demo.service.job.entity
#PageHelper#
pagehelper.autoDialect = true
pagehelper.closeConn = true
pagehelper.offset-as-page-num = false
使用Aspect实现动态切换数据源

创建数据源名称枚举

public enum DataSourceNameEnum {
        /** 业务库 */
        BUSINESS("biz"),
        /** 定时任务库 */
        QUARTZ_JOB("job");
    /** 数据源名称 */
    private String name;

    /**
     * 
     * 构造函数
     * 
     * @param name
     */
    private DataSourceNameEnum(String name) {
        this.name = name;
    }

    /**
     * 获取:数据源名称
     */
    public String getName() {
        return name;
    }
}

自定义数据源注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSourceAnnotation {
    /** 默认使用业务数据库 */
    DataSourceNameEnum value() default DataSourceNameEnum.BUSINESS;
}

数据源上下文管理器

public class DataSourceContextHolder {
    final static ThreadLocal<String> local = new ThreadLocal<>();

    public static void setDataSourceName(String name) {
        local.set(name);
    }

    public static String getDataSourceName() {
        return local.get();
    }
}

实现动态数据源

@Log4j2
public class DynamicDataSource extends AbstractRoutingDataSource {

    /**
     * @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()
     */
    @Override
    protected Object determineCurrentLookupKey() {
        String dataSourceName = DataSourceContextHolder.getDataSourceName();
        log.debug("Current data source name is {}.", dataSourceName);
        return dataSourceName;
    }
}

数据源配置管理

@Configuration
public class DataSourceConfig {
    @Bean(name = "biz")
    @ConfigurationProperties(prefix = "biz.datasource")
    public DataSource bizDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "job")
    @ConfigurationProperties(prefix = "job.datasource")
    public DataSource jobDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dataSource")
    @Primary
    public DataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        DataSource biz = bizDataSource();
        DataSource job = jobDataSource();
        dynamicDataSource.setDefaultTargetDataSource(biz);
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceNameEnum.BUSINESS.getName(), biz);
        targetDataSources.put(DataSourceNameEnum.QUARTZ_JOB.getName(), job);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }
}

使用AOP实现数据源切换

@Aspect
@Order(1)
@Component
@Log4j2
public class DataSourceAspect {
    @Pointcut("execution(* com.demo.service.job.service.impl.*Impl.*(..))")
    public void aspect() {}

    @Before("aspect()")
    private void before(JoinPoint point) {
        Object target = point.getTarget();
        String methodName = point.getSignature().getName();
        Class<?> clazz = target.getClass();
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();

        Method method = null;
        try {
            method = clazz.getMethod(methodName, parameterTypes);
        } catch (Exception e) {
            log.error("Get {}.{} ERROR", clazz.getName(), methodName);
        }
        if (null != method && method.isAnnotationPresent(DataSourceAnnotation.class)) {
            DataSourceAnnotation dataSource = method.getAnnotation(DataSourceAnnotation.class);
            String name = dataSource.value().getName();
            DataSourceContextHolder.setDataSourceName(name);
            log.debug("Switch Data Source To {}.", name);
        }
    }
}


最重要的是,关闭Spring boot自动数据源配置

// 禁用数据源自动配置
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
// 事务处理在数据源切换完成后
@EnableTransactionManagement(order = 2)
public class JobManagerApplication {
    public static void main(String[] args) {
        SpringApplication.run(JobManagerApplication.class, args);
    }
}
定时任务动态管理的实现

自定义定时任务接口

public interface BaseQuartzJob extends Job {
    void execute(JobExecutionContext executionContext) throws JobExecutionException;
}

自定义任务

@Log4j2
public class PrintJob implements BaseQuartzJob {
    @Override
    public void execute(JobExecutionContext executionContext) throws JobExecutionException {
        log.info("execute printjob now");
    }
}
@Log4j2
public class FyAssetJob implements BaseQuartzJob {
    @Autowired
    private TAssetFyLmsRunLogService assetFyLmsRunLogService;

    @Override
    public void execute(JobExecutionContext executionContext) throws JobExecutionException {
        log.info("=== check run log begin===");
        TAssetFyLmsRunLogPageParam param = new TAssetFyLmsRunLogPageParam();
        param.setPageNum(1);
        param.setPageSize(12);
        List<TAssetFyLmsRunLog> list = assetFyLmsRunLogService.getAll(param);
        if (null != list && !list.isEmpty()) {
            for (TAssetFyLmsRunLog item : list) {
                log.debug(item.toString());
            }
        }
        log.info("=== check run log end===");
    }
}

其中,第二个任务,使用了Spring IOC的Bean。

定时任务管理

@Log4j2
@RestController
public class QuartzJobController {
    @Autowired
    @Qualifier("Scheduler")
    private Scheduler scheduler;

    @Autowired
    private QuartzJobInfoService quartzJobInfoService;

    /**
     * 分页检索
     * 
     * @Title: list
     */
    @ApiOperation(value = "分页检索",
        notes = "")
    @RequestMapping(value = "/list",
        method = RequestMethod.POST)
    public ResponseEntity<BaseResponse<BasePageResult<QuartzJobInfo>>> list(
        @RequestBody BaseRequest<QuartzJobPageParam> req) {
        BaseResponse<BasePageResult<QuartzJobInfo>> response = new BaseResponse<>();
        BasePageResult<QuartzJobInfo> result = quartzJobInfoService.list(req);
        response.setResult(result);
        return new ResponseEntity<BaseResponse<BasePageResult<QuartzJobInfo>>>(response, HttpStatus.OK);
    }

    /**
     * 新增任务
     * 
     * @Title: add
     */
    @ApiOperation(value = "新增任务",
        notes = "")
    @RequestMapping(value = "/add",
        method = RequestMethod.POST)
    public ResponseEntity<BaseResponse<String>> add(@RequestBody BaseRequest<QuarzJobParam> req) {
        BaseResponse<String> response = new BaseResponse<>();
        String code = ResultCodeEnum.SUCCESS.getCode();
        String result = "新增定时任务成功!";

        // get parameter fro request
        QuarzJobParam item = req.getParam();
        String jobClassName = item.getJobClassName();
        String jobGroupName = item.getJobGroup();
        String cronExpression = item.getCornExpression();

        try {
            // build jobDetail and trigger
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())
                .withIdentity(jobClassName, jobGroupName).build();
            // 表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
                .withSchedule(scheduleBuilder).build();
            // 执行调度
            scheduler.start();
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            code = ResultCodeEnum.ERROR.getCode();
            result = "调度定时任务失败!";
            log.error("调度定时任务失败:{}", e.getMessage());
        } catch (Exception e) {
            code = ResultCodeEnum.ERROR.getCode();
            result = "构建定时任务失败!";
            log.error("构建定时任务失败:{}", e.getMessage());
        }

        response.setCode(code);
        response.setResult(result);
        return new ResponseEntity<BaseResponse<String>>(response, HttpStatus.OK);
    }

    /**
     * 暂停任务
     * 
     * @Title: pause
     */
    @ApiOperation(value = "暂停任务",
        notes = "")
    @RequestMapping(value = "/pause",
        method = RequestMethod.POST)
    public ResponseEntity<BaseResponse<String>> pause(@RequestBody BaseRequest<QuarzJobParam> req) {
        BaseResponse<String> response = new BaseResponse<>();
        String code = ResultCodeEnum.SUCCESS.getCode();
        String result = "暂停定时任务成功!";

        // get parameter fro request
        QuarzJobParam item = req.getParam();
        String jobClassName = item.getJobClassName();
        String jobGroupName = item.getJobGroup();

        try {
            scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            code = ResultCodeEnum.ERROR.getCode();
            result = "暂停定时任务失败!";
            log.error("暂停定时任务失败:{}", e.getMessage());
        }

        response.setCode(code);
        response.setResult(result);
        return new ResponseEntity<BaseResponse<String>>(response, HttpStatus.OK);
    }

    /**
     * 恢复任务
     * 
     * @Title: resume
     */
    @ApiOperation(value = "恢复任务",
        notes = "")
    @RequestMapping(value = "/resume",
        method = RequestMethod.POST)
    public ResponseEntity<BaseResponse<String>> resume(@RequestBody BaseRequest<QuarzJobParam> req) {
        BaseResponse<String> response = new BaseResponse<>();
        String code = ResultCodeEnum.SUCCESS.getCode();
        String result = "恢复定时任务成功!";

        // get parameter fro request
        QuarzJobParam item = req.getParam();
        String jobClassName = item.getJobClassName();
        String jobGroupName = item.getJobGroup();

        try {
            scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            code = ResultCodeEnum.ERROR.getCode();
            result = "恢复定时任务失败!";
            log.error("恢复定时任务失败:{}", e.getMessage());
        }

        response.setCode(code);
        response.setResult(result);
        return new ResponseEntity<BaseResponse<String>>(response, HttpStatus.OK);
    }

    /**
     * 删除任务
     * 
     * @Title: remove
     */
    @ApiOperation(value = "删除任务",
        notes = "")
    @RequestMapping(value = "/remove",
        method = RequestMethod.POST)
    public ResponseEntity<BaseResponse<String>> remove(@RequestBody BaseRequest<QuarzJobParam> req) {
        BaseResponse<String> response = new BaseResponse<>();
        String code = ResultCodeEnum.SUCCESS.getCode();
        String result = "删除定时任务成功!";

        // get parameter fro request
        QuarzJobParam item = req.getParam();
        String jobClassName = item.getJobClassName();
        String jobGroupName = item.getJobGroup();

        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
            scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
        } catch (SchedulerException e) {
            code = ResultCodeEnum.ERROR.getCode();
            result = "删除定时任务失败!";
            log.error("删除定时任务失败:{}", e.getMessage());
        }

        response.setCode(code);
        response.setResult(result);
        return new ResponseEntity<BaseResponse<String>>(response, HttpStatus.OK);
    }

    /**
     * 更新任务触发器
     * 
     * @Title: refresh
     */
    @ApiOperation(value = "更新任务",
        notes = "")
    @RequestMapping(value = "/refresh",
        method = RequestMethod.POST)
    public ResponseEntity<BaseResponse<String>> refresh(@RequestBody BaseRequest<QuarzJobParam> req) {
        BaseResponse<String> response = new BaseResponse<>();
        String code = ResultCodeEnum.SUCCESS.getCode();
        String result = "更新定时任务成功!";

        // get parameter fro request
        QuarzJobParam item = req.getParam();
        String jobClassName = item.getJobClassName();
        String jobGroupName = item.getJobGroup();
        String cronExpression = item.getCornExpression();

        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            code = ResultCodeEnum.ERROR.getCode();
            result = "更新定时任务失败!";
            log.error("更新定时任务失败:{}", e.getMessage());
        }

        response.setCode(code);
        response.setResult(result);
        return new ResponseEntity<BaseResponse<String>>(response, HttpStatus.OK);
    }

    /**
     * 获得任务类
     * 
     * @Title: getClass
     * @throws Exception
     */
    private static BaseQuartzJob getClass(String className) throws Exception {
        Class<?> clazz = Class.forName(className);
        return (BaseQuartzJob) clazz.newInstance();
    }
}

主要的代码已经帖完了,看一下工程架构

启动项目,使用SWAGGER查看API

可以使用swagger直接进行测试,将我们编写的两个定时任务添加到定时任务调度器中。

下图是定时任务的执行日志


使用Spring BootQuartz实现定时任务管理,可以让你更方便地管理和监控你的定时任务。下面是一个使用Spring BootQuartzSpring MVC实现定时任务管理的示例: 首先,在你的Spring Boot应用程序中添加QuartzSpring MVC的依赖项: ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ``` 然后,在你的Spring Boot应用程序中创建一个Quartz的调度器,并添加一个Spring MVC的Controller来管理定时任务: ```java @Configuration public class QuartzConfig { @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setTriggers(myTaskTrigger().getObject()); return schedulerFactoryBean; } @Bean public JobDetailFactoryBean myTaskJob() { JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean(); jobDetailFactoryBean.setJobClass(MyTask.class); return jobDetailFactoryBean; } @Bean public CronTriggerFactoryBean myTaskTrigger() { CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean(); cronTriggerFactoryBean.setJobDetail(myTaskJob().getObject()); cronTriggerFactoryBean.setCronExpression("0/5 * * * * ?"); // 每5秒执行一次 return cronTriggerFactoryBean; } } @RestController public class TaskController { @Autowired private Scheduler scheduler; @PostMapping("/tasks") public void addTask(@RequestBody TaskInfo taskInfo) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(taskInfo.getJobClass()) .withIdentity(taskInfo.getJobName(), taskInfo.getJobGroup()) .build(); CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity(taskInfo.getTriggerName(), taskInfo.getTriggerGroup()) .withSchedule(CronScheduleBuilder.cronSchedule(taskInfo.getCronExpression())) .build(); scheduler.scheduleJob(jobDetail, trigger); } @DeleteMapping("/tasks/{jobName}/{jobGroup}") public void deleteTask(@PathVariable String jobName, @PathVariable String jobGroup) throws SchedulerException { JobKey jobKey = new JobKey(jobName, jobGroup); scheduler.deleteJob(jobKey); } } ``` 在上面的代码中,我们创建了一个Spring MVC的Controller来管理定时任务。我们使用了Scheduler类来添加和删除定时任务。在添加定时任务时,我们使用了TaskInfo类来封装定时任务的信息。在删除定时任务时,我们使用了jobName和jobGroup来识别定时任务。 最后,在你的定时任务类中实现Job接口,并在类上添加@DisallowConcurrentExecution注解,以确保每个任务执行时只有一个实例: ```java @Component @DisallowConcurrentExecution public class MyTask implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 定时任务执行的代码 } } ``` 以上就是使用Spring BootQuartzSpring MVC实现定时任务管理的示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值