springboot-quartz ,定時任務 (添加、刪除、暫停、恢復)


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

 

  

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM