主要是想实现这个功能,用户注册时,自定义开始时间(date)和时长(time),当开始时间(date)一到,将用户的status从0变为1,当开始时间(date)+时长(time)一到即结束时间(date),将用户的status从1变为2。如下图所示

Java Quartz任务取消 quartz停止一个任务_xml

 


 注册用户,输入自定义的开始日期,以及时长

Java Quartz任务取消 quartz停止一个任务_spring_02

 


 当时间到达开始时间,将用户状态变为1

Java Quartz任务取消 quartz停止一个任务_spring_03

 


  当时间到达结束时间,将用户状态变为2

Java Quartz任务取消 quartz停止一个任务_xml_04

 

 

 

一、 Quartz 的4个核心概念

  1. Job 表示一个工作,要执行的具体内容。此接口中只有一个方法,如下 

execute(JobExecutionContext context) 

  2. JobDetail 表示一个具体的可执行的调度程序,Job是这个可执行程调度程序索要执行的内容,另外JobDetail还包含了这个任务调度的方                      案和策略。

  3. Trigger 代表一个调度参数的配置,什么时候去调。

  4. Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器             调度了。

 

二、项目目录结构

Java Quartz任务取消 quartz停止一个任务_xml_05

 

 

 

Java Quartz任务取消 quartz停止一个任务_xml_06

 

 

 

三、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表 

 

Java Quartz任务取消 quartz停止一个任务_Java Quartz任务取消_07

 

 

 

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();
    }
}