主要是想实现这个功能,用户注册时,自定义开始时间(date)和时长(time),当开始时间(date)一到,将用户的status从0变为1,当开始时间(date)+时长(time)一到即结束时间(date),将用户的status从1变为2。如下图所示
注册用户,输入自定义的开始日期,以及时长
当时间到达开始时间,将用户状态变为1
当时间到达结束时间,将用户状态变为2
一、 Quartz 的4个核心概念
1. Job 表示一个工作,要执行的具体内容。此接口中只有一个方法,如下
void execute(JobExecutionContext context)
2. JobDetail 表示一个具体的可执行的调度程序,Job是这个可执行程调度程序索要执行的内容,另外JobDetail还包含了这个任务调度的方 案和策略。
3. Trigger 代表一个调度参数的配置,什么时候去调。
4. Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器 调度了。
二、项目目录结构
三、pom.xml 引入依赖
<?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.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.xej</groupId> <artifactId>springboot-quartz</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-quartz</name> <description>Demo project for Spring Boot</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.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.13</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.35</version> </dependency> <!-- quartz --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>5.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
四、在数据库中运行,创建11张qrtz表
CREATE TABLE QRTZ_JOB_DETAILS ( SCHED_NAME VARCHAR(120) NOT NULL, JOB_NAME VARCHAR(200) NOT NULL, JOB_GROUP VARCHAR(200) NOT NULL, DESCRIPTION VARCHAR(250) NULL, JOB_CLASS_NAME VARCHAR(250) NOT NULL, IS_DURABLE VARCHAR(1) NOT NULL, IS_NONCONCURRENT VARCHAR(1) NOT NULL, IS_UPDATE_DATA VARCHAR(1) NOT NULL, REQUESTS_RECOVERY VARCHAR(1) NOT NULL, JOB_DATA BLOB NULL, PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) ); CREATE TABLE QRTZ_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, JOB_NAME VARCHAR(200) NOT NULL, JOB_GROUP VARCHAR(200) NOT NULL, DESCRIPTION VARCHAR(250) NULL, NEXT_FIRE_TIME BIGINT(13) NULL, PREV_FIRE_TIME BIGINT(13) NULL, PRIORITY INTEGER NULL, TRIGGER_STATE VARCHAR(16) NOT NULL, TRIGGER_TYPE VARCHAR(8) NOT NULL, START_TIME BIGINT(13) NOT NULL, END_TIME BIGINT(13) NULL, CALENDAR_NAME VARCHAR(200) NULL, MISFIRE_INSTR SMALLINT(2) NULL, JOB_DATA BLOB NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP) ); CREATE TABLE QRTZ_SIMPLE_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, REPEAT_COUNT BIGINT(7) NOT NULL, REPEAT_INTERVAL BIGINT(12) NOT NULL, TIMES_TRIGGERED BIGINT(10) NOT NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE QRTZ_CRON_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, CRON_EXPRESSION VARCHAR(200) NOT NULL, TIME_ZONE_ID VARCHAR(80), PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE QRTZ_SIMPROP_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, STR_PROP_1 VARCHAR(512) NULL, STR_PROP_2 VARCHAR(512) NULL, STR_PROP_3 VARCHAR(512) NULL, INT_PROP_1 INT NULL, INT_PROP_2 INT NULL, LONG_PROP_1 BIGINT NULL, LONG_PROP_2 BIGINT NULL, DEC_PROP_1 NUMERIC(13,4) NULL, DEC_PROP_2 NUMERIC(13,4) NULL, BOOL_PROP_1 VARCHAR(1) NULL, BOOL_PROP_2 VARCHAR(1) NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE QRTZ_BLOB_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, BLOB_DATA BLOB NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) ); CREATE TABLE QRTZ_CALENDARS ( SCHED_NAME VARCHAR(120) NOT NULL, CALENDAR_NAME VARCHAR(200) NOT NULL, CALENDAR BLOB NOT NULL, PRIMARY KEY (SCHED_NAME,CALENDAR_NAME) ); CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP) ); CREATE TABLE QRTZ_FIRED_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, ENTRY_ID VARCHAR(95) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, INSTANCE_NAME VARCHAR(200) NOT NULL, FIRED_TIME BIGINT(13) NOT NULL, SCHED_TIME BIGINT(13) NOT NULL, PRIORITY INTEGER NOT NULL, STATE VARCHAR(16) NOT NULL, JOB_NAME VARCHAR(200) NULL, JOB_GROUP VARCHAR(200) NULL, IS_NONCONCURRENT VARCHAR(1) NULL, REQUESTS_RECOVERY VARCHAR(1) NULL, PRIMARY KEY (SCHED_NAME,ENTRY_ID) ); CREATE TABLE QRTZ_SCHEDULER_STATE ( SCHED_NAME VARCHAR(120) NOT NULL, INSTANCE_NAME VARCHAR(200) NOT NULL, LAST_CHECKIN_TIME BIGINT(13) NOT NULL, CHECKIN_INTERVAL BIGINT(13) NOT NULL, PRIMARY KEY (SCHED_NAME,INSTANCE_NAME) ); CREATE TABLE QRTZ_LOCKS ( SCHED_NAME VARCHAR(120) NOT NULL, LOCK_NAME VARCHAR(40) NOT NULL, PRIMARY KEY (SCHED_NAME,LOCK_NAME) );
五、添加quartz.properties文件(我是存放在resources下)
#======================================================= #调度器配置 #======================================================= org.quartz.scheduler.instanceId=AUTO org.quartz.scheduler.instanceName=project1QuartzScheduler org.quartz.scheduler.rmi.export=false org.quartz.scheduler.rmi.proxy=false #======================================================= #线程池配置 #======================================================= org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount=5 org.quartz.threadPool.threadPriority=5 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true #======================================================= #JobStore配置 #======================================================= org.quartz.jobStore.misfireThreshold=60000 org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.isClustered=false org.quartz.jobStore.tablePrefix=QRTZ_ org.quartz.jobStore.dataSource=myDS #======================================================= #数据库配置 #======================================================= org.quartz.dataSource.myDS.driver= com.mysql.jdbc.Driver org.quartz.dataSource.myDS.URL= jdbc:mysql:///db_quartz?characterEncoding=utf8&serverTimezone=UTC org.quartz.dataSource.myDS.user= root org.quartz.dataSource.myDS.password=123456 org.quartz.dataSource.myDS.maxConnections=5
六、自定义JobFactory
原因
因为定时任务Job对象的实例化过程是在Quartz中进行的,QuartzService Bean是由Spring容器管理的,Quartz根本察觉不 到QuartzService Bean的存在,所以无法将 QuartzService Bean装配到Job对象中
Job对象的实例化,是由SchedulerFactoryBean使用AdaptableJobFactory创建的,如果未指定,会自动创建
解决步骤
将Job Bean也加入Spring 容器管理之中,Spring容器能够为Job Bean自动装配好所需的依赖,因此需要重写JobFactory,然后 创建SchedulerFactoryBean,并指定创建Job实例为自定义的JobFactory工厂
1. 创建一个自定义的JobFactory,使用Spring容器管理的Quartz的Bean(Job)
创建一个MyJobFactory 类,@Component,表示该类是由Spring管理的一个组件
package cn.xej.config; 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; import org.springframework.util.ReflectionUtils; @Component public class MyJobFactory extends AdaptableJobFactory { @Autowired private AutowireCapableBeanFactory capableBeanFactory; /** * 创建Job实例 */ protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { // 实例化对象 Object jobInstance = super.createJobInstance(bundle); // 进行注入(Spring管理该Bean) capableBeanFactory.autowireBean(jobInstance); // 返回对象 return jobInstance; } }
2. 创建一个SchedulerFactoryBean 实例,并将其Job实例化的工厂指定为一个Spring容器中的自定义MyJobFactory实例,创建 一个SchedulerConfig 配 置类
package cn.xej.config; import org.quartz.Scheduler; import org.springframework.beans.factory.annotation.Autowired; 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 SchedulerConfig { @Autowired private MyJobFactory myJobFactory; //一个由Spring管理的自定义创建Job实例的工厂 /** * 配置SchedulerFactoryBean //创建一个SchedulerFactoryBean 实例 */ @Bean // 将一个方法产生为Bean并交给Spring容器管理 public SchedulerFactoryBean schedulerFactoryBean(){
// Spring提供SchedulerFactoryBean为Scheduler提供配置信息,并被Spring容器管理其生命周期 SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); // 延时启动(秒)
schedulerFactoryBean.setStartupDelay(1);
// 设置quartz的配置文件 schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));
// 设置自定义Job Factory,用于Spring管理Job Bean schedulerFactoryBean.setJobFactory(myJobFactory); return schedulerFactoryBean; } @Bean public Scheduler scheduler(){
// 创建一个调度容器,并由Spring管理 return schedulerFactoryBean().getScheduler(); } }
七、 编写定时任务(1个开始,1个结束)
1. 创建一个开始任务StartUserJob
package cn.xej.job; import cn.xej.service.UserService; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.QuartzJobBean; public class StartUserJob extends QuartzJobBean { @Autowired private UserService userService; @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("开始将用户status改为1"); JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); String userId = (String) jobDataMap.get("userId"); Integer time = (Integer) jobDataMap.get("time"); String date = (String) jobDataMap.get("date"); System.out.println("用户注册开始id: "+userId+" 时长: "+time+" 开始日期: "+date); // 写自己的方法 userService.startUpdateUserStatus(userId,time,date); } }
2. 创建一个结束任务CloseUserJob
package cn.xej.job; import cn.xej.service.UserService; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.QuartzJobBean; public class CloseUserJob extends QuartzJobBean { @Autowired private UserService userService; @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("结束将用户status改为2"); JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); String userId = (String) jobDataMap.get("userId"); System.out.println("用户注册结束id: "+userId); // 写自己的方法 userService.closeUpdateUserStatus(userId); } }
八、创建一个具有添加定时任务、移除、暂停、恢复,QuartzService接口,以及QuartzServiceimpl实现接口
package cn.xej.service; import org.quartz.JobDataMap; import org.quartz.SchedulerException; import org.springframework.scheduling.quartz.QuartzJobBean; public interface QuartzService { /** * 添加定时任务 */ void addJob(String jobName, String jobGroup, String cron, Class<? extends QuartzJobBean> jobClass, JobDataMap jobDataMap) throws SchedulerException; /** * 删除定时任务 */ void delJob(String jobName, String jobGroup); /** * 暂停定时任务 */ void pauseJob(String jobName, String jobGroup); /** * 继续定时任务 */ void resumeJob(String jobName, String jobGroup); }
package cn.xej.service.impl; import cn.xej.service.QuartzService; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.stereotype.Service; @Service public class QuartzServiceimpl implements QuartzService { @Autowired private Scheduler scheduler; // 在SchedulerConfig配置类中 已经由Spring管理,所以这里可以自动注入
/**
* jobName 任务名 自定义
* jobGroup 任务组 自定义
* cron 时间表达式
* jobClass 任务实现类 如 StartUserJob 或 CloseUserJob
* jobDataMap 自定义参数
**/
// 添加定时任务 @Override public void addJob(String jobName, String jobGroup, String cron, Class<? extends QuartzJobBean> jobClass, JobDataMap jobDataMap) { try { /** * 构建JobDetail (表示一个具体的可执行的调度程序,Job是这个可执行调度程序所要执行的内容) */ JobDetail jobDetail = JobBuilder.newJob(jobClass) .withIdentity(jobName,jobGroup) .usingJobData(jobDataMap) .build(); /** * 构建出发去Trigger (调度参数的配置,代表何时出发该任务) */ CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron); CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity(jobName,jobGroup) .startNow() .withSchedule(scheduleBuilder) .build(); scheduler.scheduleJob(jobDetail,trigger); scheduler.start(); System.out.println("添加定时任务成功"); } catch (SchedulerException e) { e.printStackTrace(); } } // 删除定时任务 @Override public void delJob(String jobName, String jobGroup) { try { // TriggerKey 定义了trigger的名称和组别 ,通过任务名和任务组名获取TriggerKey TriggerKey triggerKey = TriggerKey.triggerKey(jobName,jobGroup); // 停止触发器 scheduler.resumeTrigger(triggerKey);
// 移除触发器 scheduler.unscheduleJob(triggerKey); // 移除任务 scheduler.deleteJob(JobKey.jobKey(jobName,jobGroup)); System.out.println("删除定时任务成功"); } catch (SchedulerException e) { e.printStackTrace(); } } // 暂停定时任务 @Override public void pauseJob(String jobName, String jobGroup) { try { JobKey jobKey = JobKey.jobKey(jobName,jobGroup); // 暂停任务 scheduler.pauseJob(jobKey); System.out.println("暂停定时任务成功"); } catch (SchedulerException e) { e.printStackTrace(); } } // 继续定时任务 @Override public void resumeJob(String jobName, String jobGroup) { try {
// 通过任务名和任务组名获取jobKey JobKey jobKey = JobKey.jobKey(jobName,jobGroup); // 继续任务 scheduler.resumeJob(jobKey); System.out.println("继续定时任务成功"); } catch (SchedulerException e) { e.printStackTrace(); } } }
九、注册页面 register.html
<form> 账号 <input type="text" name="userId" id="userId"><br/> 密码 <input type="password" name="password" id="password"><br/> 性名 <input type="text" name="name" id="name"><br/> 日期 <input type="text" name="date" id="date"><br/> 时长 <input type="text" name="time" id="time"><br/> <button type="button" onclick="register()">注册</button> </form> <script> function register() { var userId = $('#userId').val(); var password = $('#password').val(); var name = $('#name').val(); var date = $('#date').val(); var time = $('#time').val(); $.ajax({ url: '/user/toRegister', type: 'post', data: { userId: userId, password: password, name: name, date: date, time: time }, success: function (dt) { if(dt.code===200){ alert('注册成功'); } } }) } </script>
十、UserController控制器
@Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/toRegister") @ResponseBody public RespObj toRegister(String userId, String password, String name, String date, Integer time) { return userService.addUser(userId, password, name, date, time); } }
十一、UserService接口以及UserServiceimpl实现类
当用户注册时,首先获取前端注册页面获得的参数(userId,password,name,date,time),然后要将date装换成cron表达式,添加定时器
执行顺序为: UserController --》UserServiceimpl --》QuartzServiceimpl --》(等待自定义开始日期到达然后执行自定义的Job)StartUserJob
--》 UserServiceimpl 的 startUpdateUserStatus方法(删除开始的定时任务,新增结束的定时任务),同理结束任务流程。
package cn.xej.service; import cn.xej.common.RespObj; import cn.xej.pojo.User; import javax.servlet.http.HttpServletResponse; import java.util.List; public interface UserService { public User findByUserId(String userId); public List<User> getAllUser(); public RespObj addUser(String userId, String password, String name, String date, Integer time); public RespObj startUpdateUserStatus(String userId, Integer time, String date); public RespObj closeUpdateUserStatus(String userId); public RespObj stopJob(String userId); public RespObj resumeJob(String userId); public RespObj delJob(String userId); }
package cn.xej.service.impl; import cn.xej.common.RespObj; import cn.xej.common.Utils; import cn.xej.job.CloseUserJob; import cn.xej.job.StartUserJob; import cn.xej.mapper.UserDao; import cn.xej.pojo.User; import cn.xej.service.QuartzService; import cn.xej.service.UserService; import org.quartz.JobDataMap; import org.quartz.SchedulerException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.ResourceUtils; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; @Service public class UserServiceimpl implements UserService { private final Logger log = LoggerFactory.getLogger(getClass()); @Autowired private UserDao userDao; @Autowired private QuartzService quartzService; @Override public User findByUserId(String userId) { return userDao.findByUserId(userId); } @Override public List<User> getAllUser() { return userDao.getAllUser(); } // 用户注册时,添加定时任务 @Override public RespObj addUser(String userId, String password, String name, String date, Integer time) { User user = new User(); user.setUserId(userId); user.setPassword(password); user.setName(name); user.setStatus(0); /* //获得SimpleDateFormat类,我们转换为yyyy-MM-dd的时间格式 SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { //使用SimpleDateFormat的parse()方法生成Date Date date1 = sf.parse(date); //打印Date System.out.println(date1); user.setDate(date1); } catch (ParseException e) { e.printStackTrace(); } */ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); GregorianCalendar calendar = new GregorianCalendar(); try{ calendar.setTime(sdf.parse(date)); Date date1 = calendar.getTime(); user.setDate(date1); }catch (ParseException e) { e.printStackTrace(); } user.setTime(time); // 添加注册的用户 userDao.addUser(user); // 添加定时任务,jobDataMap为自定义要的传参的内容,将在StartUserJob中获取 JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("userId",userId); jobDataMap.put("time",time); jobDataMap.put("date",date);
// 将页面传的date 装换成 cron表达式 String cronExpression = Utils.dateStrConvertCronExpression(date,null); System.out.println("开始日期: "+cronExpression); try { quartzService.addJob("START_USER"+userId,"USER",cronExpression, StartUserJob.class,jobDataMap); } catch (SchedulerException e) { e.printStackTrace(); } return RespObj.build(200,"success",null); } @Override public RespObj startUpdateUserStatus(String userId, Integer time, String date) { log.info("开始改变用户status为1:"+userId); // 修改用户状态为:1 userDao.startUpdateUserStatus(userId); // 删除开始注册的定时任务 quartzService.delJob("START_USER"+userId,"USER"); // 新增一个注册结束的定时任务 JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("userId",userId); String cronExpression = Utils.dateStrConvertCronExpression(date, time); try { quartzService.addJob("CLOSE_USER"+userId,"USER",cronExpression, CloseUserJob.class,jobDataMap); } catch (SchedulerException e) { e.printStackTrace(); } return RespObj.build(200,"success",null); } @Override public RespObj closeUpdateUserStatus(String userId) { log.info("用户注册结束用户状态为2.:"+userId); // 修改用户状态为:2 userDao.closeUpdateUserStatus(userId); // 删除考试结束的定时任务 quartzService.delJob("CLOSE_USER"+userId,"USER"); return RespObj.build(200,"success",null); }
// 暂停任务 @Override public RespObj stopJob(String userId) { User user = userDao.findByUserId(userId); if(user.getStatus()==2){ return RespObj.build(400,"fail","任务已结束"); } quartzService.pauseJob("CLOSE_USER"+userId,"USER"); // 实现暂停 return RespObj.build(200,"success",null); }
// 恢复任务 @Override public RespObj resumeJob(String userId) { User user = userDao.findByUserId(userId); if(user.getStatus()==2){ return RespObj.build(400,"fail","任务已结束"); } quartzService.resumeJob("CLOSE_USER"+userId,"USER"); return RespObj.build(200,"success",null); }
// 移除任务 @Override public RespObj delJob(String userId) { User user = userDao.findByUserId(userId); if(user.getStatus()==2){ return RespObj.build(400,"fail","任务已结束"); }else if(user.getStatus()==0){ return RespObj.build(400,"fail","任务未开始"); } quartzService.delJob("CLOSE_USER"+userId,"USER"); return RespObj.build(200,"success",null); } }
十二、将时间日期字符串转换成cron表达式
package cn.xej.common; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class Utils { /** * 将时间日期字符串转换成cron表达式 * @param dateStr * @return */ public static String dateStrConvertCronExpression(String dateStr,Integer minute){ DateTimeFormatter localDateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime date = LocalDateTime.parse(dateStr, localDateTimeFormat); if(minute != null) date = date.plusMinutes(minute); StringBuilder sb = new StringBuilder(); sb.append(date.getSecond()).append(" ") .append(date.getMinute()).append(" ") .append(date.getHour()).append(" ") .append(date.getDayOfMonth()).append(" ") .append(date.getMonthValue()).append(" ") .append("?"); return sb.toString(); } }