主要是想實現這個功能,用戶注冊時,自定義開始時間(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(); } }