springBoot动态整合Quartz
- 2020 年 2 月 13 日
- 笔记
动态Quart定时任务 项目目录:
Sql文件:
创建表: CREATE TABLE `sys_task` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL COMMENT '任务名', `content` varchar(50) DEFAULT NULL COMMENT '任务描述', `cron_expression` varchar(30) NOT NULL COMMENT '七子表达式', `class_method` varchar(200) NOT NULL COMMENT '任务执行时调用哪个类的方法 包名+类名', `state` varchar(1) NOT NULL COMMENT '任务状态 0:未启动 1:启动', `job_group` varchar(20) NOT NULL COMMENT '分组+名字会生成一个job任务 两者+相加不能重复!!!', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=36 DEFAULT CHARSET=utf8; 插入测试数据: INSERT INTO `cnbuilder`.`sys_task` ( `id`, `name`, `content`, `cron_expression`, `class_method`, `state`, `job_group`, `create_time`, `update_time` ) VALUES ( 1, 'helloword', '测试', '0/10 * * * * ?', 'cn.cnbuilder.trendsquartz.task.HelloWorldJob', '0', 'TEST_GROUP', '2018-06-29 23:31:42', '2018-06-29 23:31:42' );
java代码
config: package cn.cnbuilder.trendsquartz.config; import cn.cnbuilder.trendsquartz.factory.JobFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import java.io.IOException; import java.util.Properties; import org.quartz.Scheduler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.scheduling.quartz.SchedulerFactoryBean; @Configuration public class QuartzConfig { @Autowired private JobFactory jobFactory; @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); try { //覆盖原来的任务 schedulerFactoryBean.setOverwriteExistingJobs(true); //容器工厂 schedulerFactoryBean.setJobFactory(jobFactory); } catch (Exception e) { e.printStackTrace(); } return schedulerFactoryBean; } // 创建schedule @Bean(name = "scheduler") public Scheduler scheduler() { return schedulerFactoryBean().getScheduler(); } }
JobFactory: package cn.cnbuilder.trendsquartz.factory; import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.scheduling.quartz.AdaptableJobFactory; import org.springframework.stereotype.Component; @Component public class JobFactory extends AdaptableJobFactory { //这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴. //为什么需要这个类呢,在我写的这个demo中,大家可以将此类删掉,发现程序也可以政策运营,可是我为什么还是加上呢。 //大家可以看下我们的任务类,大家可以看到Job对象的实例化过程是在Quartz中进行的,这时候我们将spring的东西注入进来,肯定是行不通的,所以需要这个类 @Autowired private AutowireCapableBeanFactory capableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { //调用父类的方法 Object jobInstance = super.createJobInstance(bundle); //进行注入 capableBeanFactory.autowireBean(jobInstance); return jobInstance; } }
ScheduleJobInitListener: package cn.cnbuilder.trendsquartz.listenner; import cn.cnbuilder.trendsquartz.service.ScheduleJobService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(value = 1) public class ScheduleJobInitListener implements CommandLineRunner { @Autowired ScheduleJobService scheduleJobService; @Override public void run(String... arg0) throws Exception { try { //初始化 scheduleJobService.initSchedule(); } catch (Exception e) { e.printStackTrace(); } } }
ScheduleJobService: package cn.cnbuilder.trendsquartz.service; import org.quartz.SchedulerException; import java.util.List; /** * 初始化定时任务工作 */ public interface ScheduleJobService { void initSchedule() throws SchedulerException; }
ScheduleJobServiceImpl: package cn.cnbuilder.trendsquartz.service.impl; import cn.cnbuilder.trendsquartz.enums.JobStatusEnum; import cn.cnbuilder.trendsquartz.mapper.JobsMapper; import cn.cnbuilder.trendsquartz.service.ScheduleJobService; import cn.cnbuilder.trendsquartz.utils.QuartzManager; import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class ScheduleJobServiceImpl implements ScheduleJobService { @Autowired private JobsMapper jobsMapper; @Autowired QuartzManager quartzManager; @Override public void initSchedule() throws SchedulerException { // 这里获取任务信息数据 List<Map> jobList = jobsMapper.list(); for (Map map : jobList) { if (JobStatusEnum.RUNNING.getCode().equals(map.get("state"))) { quartzManager.addJob(map); } } } }
JobsController: package cn.cnbuilder.trendsquartz.controller; import cn.cnbuilder.trendsquartz.enums.JobStatusEnum; import cn.cnbuilder.trendsquartz.service.JobsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; /** * quartz 控制层 */ @Controller @RequestMapping("/job") public class JobsController { @Autowired private JobsService jobsService; @ResponseBody @PostMapping("/slectAll") public List<Map> slectAll() { // 查询列表数据 List<Map> result = jobsService.list(); return result; } @PostMapping("/edit") @ResponseBody public String edit( String name, String content, String cron_expression, String class_method, String job_group, Long id ) { Map job = jobsService.get(id); if (JobStatusEnum.RUNNING.getCode().equals(job.get("state"))) { return "修改之前请先停止任务!"; } jobsService.updateJob(name, content, cron_expression, class_method, job_group, id, job.get("state").toString()); return "success"; } @PostMapping("/changeStatus/{id}") @ResponseBody public String changeStatus(@PathVariable("id") Long id, Boolean jobStatus) { String status = jobStatus == true ? JobStatusEnum.RUNNING.getCode() : JobStatusEnum.STOP.getCode(); try { jobsService.changeStatus(id, status); return "success"; } catch (Exception e) { e.printStackTrace(); } return "任务状态修改失败"; } /** * 删除 */ @PostMapping("/remove/{id}") @ResponseBody public String remove(@PathVariable("id") Long id) { Map taskServer = jobsService.get(id); if (JobStatusEnum.RUNNING.getCode().equals(taskServer.get("state").toString())) { return "删除前请先停止任务!"; } if (jobsService.remove(id) > 0) { return "success"; } return "删除任务失败! "; } /** * 批量删除 */ @PostMapping("/removeBatch") @ResponseBody public String removeBatch(@RequestParam("ids[]") Long[] ids) { for (Long id : ids) { Map taskServer = jobsService.get(id); if (JobStatusEnum.RUNNING.getCode().equals(taskServer.get("state").toString())) { return "删除前请先停止任务!"; } } jobsService.removeBatch(ids); return "success"; } /** * 新增保存 */ @ResponseBody @PostMapping("/save") public String save( String name, String content, String cron_expression, String class_method, String job_group ) { if (jobsService.save(name, content, cron_expression, class_method, job_group) > 0) { return "success"; } return "新增任务失败!"; } }
jobService: package cn.cnbuilder.trendsquartz.service; import org.quartz.SchedulerException; import java.util.List; import java.util.Map; /** * JobsService */ public interface JobsService { Map get(Long id); List<Map> list(); int save(String name, String content, String cron_expression, String class_method, String group); int updateJob(String name, String content, String cron_expression, String class_method, String job_group, Long id, String state); int remove(Long id); int removeBatch(Long[] ids); void changeStatus(Long jobId, String jobStatus) throws SchedulerException; void updateCron(Long jobId) throws SchedulerException; }
JobsServiceImpl: package cn.cnbuilder.trendsquartz.service.impl; import cn.cnbuilder.trendsquartz.enums.JobStatusEnum; import cn.cnbuilder.trendsquartz.mapper.JobsMapper; import cn.cnbuilder.trendsquartz.service.JobsService; import cn.cnbuilder.trendsquartz.utils.QuartzManager; import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Handler; @Service public class JobsServiceImpl implements JobsService { @Autowired private JobsMapper jobsMapper; @Autowired QuartzManager quartzManager; @Override public Map get(Long id) { return jobsMapper.get(id); } @Override public List<Map> list() { List<Map> list = jobsMapper.list(); return list; } @Override public int save(String name, String content, String cron_expression, String class_method, String job_group) { //进行封装包装 HashMap<String, Object> job = new HashMap<>(); job.put("name", name); job.put("content", content); job.put("cron_expression", cron_expression); job.put("class_method", class_method); job.put("job_group", job_group); job.put("create_time", new Date()); job.put("update_time", new Date()); //默认关闭定时任务 job.put("state", 0); return jobsMapper.save(job); } @Override public int updateJob(String name, String content, String cron_expression, String class_method, String job_group, Long id, String state) { HashMap<String, Object> job = new HashMap<>(); job.put("name", name); job.put("content", content); job.put("cron_expression", cron_expression); job.put("class_method", class_method); job.put("job_group", job_group); job.put("update_time", new Date()); job.put("id", id); job.put("state", state); return jobsMapper.update(job); } @Override public int remove(Long id) { try { Map job = get(id); quartzManager.deleteJob(job); return jobsMapper.remove(id); } catch (SchedulerException e) { e.printStackTrace(); return 0; } } @Override public int removeBatch(Long[] ids) { for (Long id : ids) { try { Map task = get(id); quartzManager.deleteJob(task); } catch (SchedulerException e) { e.printStackTrace(); return 0; } } return jobsMapper.removeBatch(ids); } @Override public void changeStatus(Long jobId, String jobStatus) throws SchedulerException { Map job = get(jobId); if (job == null) { return; } if (JobStatusEnum.STOP.getCode().equals(jobStatus)) { //暂停job quartzManager.deleteJob(job); job.put("state", 0); } else { job.put("state", 1); //直接启动 quartzManager.addJob(job); } updateJob(job.get("name").toString(), job.get("content").toString(), job.get("cron_expression").toString(), job.get("class_method").toString(), job.get("job_group").toString(), jobId, job.get("state").toString()); } @Override public void updateCron(Long jobId) throws SchedulerException { Map job = get(jobId); if (job == null) { return; } if (JobStatusEnum.RUNNING.getCode().equals(job.get("state").toString())) { quartzManager.updateJobCron(job); } updateJob(job.get("name").toString(), job.get("content").toString(), job.get("cron_expression").toString(), job.get("class_method").toString(), job.get("job_group").toString(), jobId, job.get("state").toString()); } }
JobsMapper: package cn.cnbuilder.trendsquartz.mapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; import java.util.Map; @Mapper public interface JobsMapper { Map get(Long id); List<Map> list(); int save(Map job); int update(Map task); int remove(Long id); int removeBatch(Long[] ids); }
QuartzMapper.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.cnbuilder.trendsquartz.mapper.JobsMapper"> <select id="get" parameterType="java.lang.Long" resultType="map"> select id, name, content, cron_expression, class_method, state, job_group, create_time, update_time from sys_task where id = #{id,jdbcType=BIGINT} </select> <select id="list" resultType="map"> select id, name, content, cron_expression, class_method, state, job_group, create_time, update_time from sys_task order by id asc </select> <insert id="save" parameterType="map"> insert into sys_task (id, name, content, cron_expression, class_method, state, job_group, create_time, update_time) values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{content,jdbcType=VARCHAR}, #{cron_expression,jdbcType=VARCHAR}, #{class_method,jdbcType=VARCHAR}, #{state,jdbcType=VARCHAR}, #{job_group,jdbcType=VARCHAR}, #{create_time,jdbcType=TIMESTAMP}, #{update_time,jdbcType=TIMESTAMP}) </insert> <update id="update" parameterType="map"> update sys_task <set> <if test="name != null"> name = #{name,jdbcType=VARCHAR}, </if> <if test="content != null"> content = #{content,jdbcType=VARCHAR}, </if> <if test="cronExpression != null"> cron_expression = #{cron_expression,jdbcType=VARCHAR}, </if> <if test="class_method != null"> class_method = #{class_method,jdbcType=VARCHAR}, </if> <if test="state != null"> state = #{state,jdbcType=VARCHAR}, </if> <if test="job_group != null"> job_group = #{job_group,jdbcType=VARCHAR}, </if> <if test="createTime != null"> create_time = #{create_time,jdbcType=TIMESTAMP}, </if> <if test="updateTime != null"> update_time = #{update_time,jdbcType=TIMESTAMP}, </if> </set> where id = #{id,jdbcType=BIGINT} </update> <delete id="remove"> delete from sys_task where id = #{id,jdbcType=BIGINT} </delete> <delete id="removeBatch"> delete from sys_task where id in <foreach item="id" collection="array" open="(" separator="," close=")"> #{id} </foreach> </delete> </mapper>
application.yml: spring: profiles: active: dev #选择要用那个配置文件 application-dev.yml: #项目端口号访问路径 server: port: 12001 servlet: context-path: / #spring spring: # mysql 配置 datasource: driver-class-name: com.mysql.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource url: jdbc:mysql://127.0.0.1/cnbuilder?useUnicode=true&characterEncoding=UTF-8 username: root password: root #mybatis mybatis-plus: mapper-locations: classpath:/mapper/*Mapper.xml #实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: cn.cnbuilder.trendsquartz.entity global-config: # 数据库相关配置 db-config: #主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID"; id-type: id_worker #字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断" field-strategy: not_empty #驼峰下划线转换 column-underline: true #数据库大写下划线转换 # capital-mode: true #逻辑删除配置 logic-delete-value: 0 logic-not-delete-value: 1 #刷新mapper 调试神器 refresh: true # 原生配置 configuration: map-underscore-to-camel-case: true cache-enabled: false
TrendsquartzApplication: package cn.cnbuilder.trendsquartz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootAppTrendsquartzApplicationlication public class TrendsquartzApplication { public static void main(String[] args) { SpringApplication.run(TrendsquartzApplication.class, args); } }
HelloWorldJob: package cn.cnbuilder.trendsquartz.task; import org.quartz.DisallowConcurrentExecution; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.stereotype.Component; import java.util.Date; @DisallowConcurrentExecution //作业不并发 @Component public class HelloWorldJob implements Job { @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("欢迎使用定时任务 "+ new Date()); } }
pom文件: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.cnbuilder</groupId> <artifactId>trendsquartz</artifactId> <version>0.0.1-SNAPSHOT</version> <name>trendsquartz</name> <description>SpringBoot动态quartzDemo</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- quartz --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.7.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
终、、本文就是Springboot整合动态Quartz,有什么问题可以联系我。
本文用到的代码下载链接: https://pan.baidu.com/s/1597HW2OZNM2hS8YV2-IsOA 提取码: 62zq