1. 程式人生 > 其它 >spring-boot整合Quartz-job儲存方式一JDBC

spring-boot整合Quartz-job儲存方式一JDBC

1、專案jar包依賴引入

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

2、資料庫建job執行表,可以詳見quartz官方建表指令碼

注意,在postgresql下有部分型別轉換問題,mysql完美相容

3、yml配置檔案的配置

  ## quartz定時任務,採用資料庫方式,driverDelegateClass是為相容pgl資料庫增加的
  quartz:
      job
-store-type: jdbc properties: org: quartz: jobStore: driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate

4、實體類SysQuartzJob

package org.jeecg.modules.quartz.entity;

import java.io.Serializable;

import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data; /** * @Description: 定時任務線上管理 * @Author: jeecg-boot * @Date: 2019-01-02 * @Version: V1.0 */ @Data @TableName("sys_quartz_job") public class SysQuartzJob implements Serializable { private static final long serialVersionUID = 1L; /**id*/ @TableId(type = IdType.ID_WORKER_STR) private java.lang.String id; /**建立人*/ private java.lang.String createBy; /**建立時間*/ @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") private java.util.Date createTime; /**刪除狀態*/ private java.lang.Integer delFlag; /**修改人*/ private java.lang.String updateBy; /**修改時間*/ @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") private java.util.Date updateTime; /**任務類名*/ @Excel(name="任務類名",width=40) private java.lang.String jobClassName; /**cron表示式*/ @Excel(name="cron表示式",width=30) private java.lang.String cronExpression; /**引數*/ @Excel(name="引數",width=15) private java.lang.String parameter; /**描述*/ @Excel(name="描述",width=40) private java.lang.String description; /**狀態 0正常 -1停止*/ @Excel(name="狀態",width=15) private java.lang.Integer status; }

5、實現類SysQuartzJobServiceImpl

package org.jeecg.modules.quartz.service.impl;

import java.util.List;

import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.quartz.entity.SysQuartzJob;
import org.jeecg.modules.quartz.mapper.SysQuartzJobMapper;
import org.jeecg.modules.quartz.service.ISysQuartzJobService;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description: 定時任務線上管理
 * @Author: jeecg-boot
 * @Date: 2019-04-28
 * @Version: V1.1
 */
@Slf4j
@Service
public class SysQuartzJobServiceImpl extends ServiceImpl<SysQuartzJobMapper, SysQuartzJob> implements ISysQuartzJobService {
    @Autowired
    private SysQuartzJobMapper sysQuartzJobMapper;
    @Autowired
    private Scheduler scheduler;

    @Override
    public List<SysQuartzJob> findByJobClassName(String jobClassName) {
        return sysQuartzJobMapper.findByJobClassName(jobClassName);
    }

    /**
     * 儲存&啟動定時任務
     */
    @Override
    public boolean saveAndScheduleJob(SysQuartzJob sysQuartzJob) {
        if (CommonConstant.STATUS_NORMAL.equals(sysQuartzJob.getStatus())) {
            // 定時器新增
            this.schedulerAdd(sysQuartzJob.getJobClassName().trim(), sysQuartzJob.getCronExpression().trim(), sysQuartzJob.getParameter());
        }
        // DB設定修改
        sysQuartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);
        return this.save(sysQuartzJob);
    }

    /**
     * 恢復定時任務
     */
    @Override
    public boolean resumeJob(SysQuartzJob sysQuartzJob) {
        schedulerDelete(sysQuartzJob.getJobClassName().trim());
        schedulerAdd(sysQuartzJob.getJobClassName().trim(), sysQuartzJob.getCronExpression().trim(), sysQuartzJob.getParameter());
        sysQuartzJob.setStatus(CommonConstant.STATUS_NORMAL);
        return this.updateById(sysQuartzJob);
    }

    /**
     * 編輯&啟停定時任務
     * @throws SchedulerException 
     */
    @Override
    public boolean editAndScheduleJob(SysQuartzJob sysQuartzJob) throws SchedulerException {
        if (CommonConstant.STATUS_NORMAL.equals(sysQuartzJob.getStatus())) {
            schedulerDelete(sysQuartzJob.getJobClassName().trim());
            schedulerAdd(sysQuartzJob.getJobClassName().trim(), sysQuartzJob.getCronExpression().trim(), sysQuartzJob.getParameter());
        }else{
            scheduler.pauseJob(JobKey.jobKey(sysQuartzJob.getJobClassName().trim()));
        }
        return this.updateById(sysQuartzJob);
    }

    /**
     * 刪除&停止刪除定時任務
     */
    @Override
    public boolean deleteAndStopJob(SysQuartzJob job) {
        schedulerDelete(job.getJobClassName().trim());
        boolean ok = this.removeById(job.getId());
        return ok;
    }

    /**
     * 新增定時任務
     * 
     * @param jobClassName
     * @param cronExpression
     * @param parameter
     */
    private void schedulerAdd(String jobClassName, String cronExpression, String parameter) {
        try {
            // 啟動排程器
            scheduler.start();

            // 構建job資訊
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build();

            // 表示式排程構建器(即任務執行的時間)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            // 按新的cronExpression表示式構建一個新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName).withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            throw new JeecgBootException("建立定時任務失敗", e);
        } catch (RuntimeException e) {
            throw new JeecgBootException(e.getMessage(), e);
        }catch (Exception e) {
            throw new JeecgBootException("後臺找不到該類名:" + jobClassName, e);
        }
    }

    /**
     * 刪除定時任務
     * 
     * @param jobClassName
     */
    private void schedulerDelete(String jobClassName) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
            scheduler.deleteJob(JobKey.jobKey(jobClassName));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new JeecgBootException("刪除定時任務失敗");
        }
    }

    private static Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }

}

6、介面類SysQuartzJobController

package org.jeecg.modules.quartz.controller;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.quartz.entity.SysQuartzJob;
import org.jeecg.modules.quartz.service.ISysQuartzJobService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description: 定時任務線上管理
 * @Author: jeecg-boot
 * @Date: 2019-01-02
 * @Version:V1.0
 */
@RestController
@RequestMapping("/quartz/sysQuartzJob")
@Slf4j
public class SysQuartzJobController {
    @Autowired
    private ISysQuartzJobService quartzJobService;
    @Autowired
    private Scheduler scheduler;

    /**
     * 分頁列表查詢
     * 
     * @param sysQuartzJob
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public Result<?> queryPageList(SysQuartzJob sysQuartzJob, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
        QueryWrapper<SysQuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(sysQuartzJob, req.getParameterMap());
        Page<SysQuartzJob> page = new Page<SysQuartzJob>(pageNo, pageSize);
        IPage<SysQuartzJob> pageList = quartzJobService.page(page, queryWrapper);
        return Result.ok(pageList);

    }

    /**
     * 新增定時任務
     * 
     * @param sysQuartzJob
     * @return
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public Result<?> add(@RequestBody SysQuartzJob sysQuartzJob) {
        List<SysQuartzJob> list = quartzJobService.findByJobClassName(sysQuartzJob.getJobClassName());
        if (list != null && list.size() > 0) {
            return Result.error("該定時任務類名已存在");
        }
        quartzJobService.saveAndScheduleJob(sysQuartzJob);
        return Result.ok("建立定時任務成功");
    }

    /**
     * 更新定時任務
     * 
     * @param sysQuartzJob
     * @return
     */
    @RequestMapping(value = "/edit", method = RequestMethod.PUT)
    public Result<?> eidt(@RequestBody SysQuartzJob sysQuartzJob) {
        try {
            quartzJobService.editAndScheduleJob(sysQuartzJob);
        } catch (SchedulerException e) {
            log.error(e.getMessage(),e);
            return Result.error("更新定時任務失敗!");
        }
        return Result.ok("更新定時任務成功!");
    }

    /**
     * 通過id刪除
     * 
     * @param id
     * @return
     */
    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        SysQuartzJob sysQuartzJob = quartzJobService.getById(id);
        if (sysQuartzJob == null) {
            return Result.error("未找到對應實體");
        }
        quartzJobService.deleteAndStopJob(sysQuartzJob);
        return Result.ok("刪除成功!");

    }

    /**
     * 批量刪除
     * 
     * @param ids
     * @return
     */
    @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        if (ids == null || "".equals(ids.trim())) {
            return Result.error("引數不識別!");
        }
        for (String id : Arrays.asList(ids.split(","))) {
            SysQuartzJob job = quartzJobService.getById(id);
            quartzJobService.deleteAndStopJob(job);
        }
        return Result.ok("刪除定時任務成功!");
    }

    /**
     * 暫停定時任務
     * 
     * @param job
     * @return
     */
    @GetMapping(value = "/pause")
    //@ApiOperation(value = "暫停定時任務")
    public Result<Object> pauseJob(@RequestParam(name = "jobClassName", required = true) String jobClassName) {
        SysQuartzJob job = null;
        try {
            job = quartzJobService.getOne(new LambdaQueryWrapper<SysQuartzJob>().eq(SysQuartzJob::getJobClassName, jobClassName));
            if (job == null) {
                return Result.error("定時任務不存在!");
            }
            scheduler.pauseJob(JobKey.jobKey(jobClassName.trim()));
        } catch (SchedulerException e) {
            throw new JeecgBootException("暫停定時任務失敗");
        }
        job.setStatus(CommonConstant.STATUS_DISABLE);
        quartzJobService.updateById(job);
        return Result.ok("暫停定時任務成功");
    }

    /**
     * 啟動定時任務
     * 
     * @param job
     * @return
     */
    @GetMapping(value = "/resume")
    //@ApiOperation(value = "恢復定時任務")
    public Result<Object> resumeJob(@RequestParam(name = "jobClassName", required = true) String jobClassName) {
        SysQuartzJob job = quartzJobService.getOne(new LambdaQueryWrapper<SysQuartzJob>().eq(SysQuartzJob::getJobClassName, jobClassName));
        if (job == null) {
            return Result.error("定時任務不存在!");
        }
        quartzJobService.resumeJob(job);
        //scheduler.resumeJob(JobKey.jobKey(job.getJobClassName().trim()));
        return Result.ok("恢復定時任務成功");
    }

    /**
     * 通過id查詢
     * 
     * @param id
     * @return
     */
    @RequestMapping(value = "/queryById", method = RequestMethod.GET)
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        SysQuartzJob sysQuartzJob = quartzJobService.getById(id);
        return Result.ok(sysQuartzJob);
    }

    /**
     * 匯出excel
     * 
     * @param request
     * @param response
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, SysQuartzJob sysQuartzJob) {
        // Step.1 組裝查詢條件
        QueryWrapper<SysQuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(sysQuartzJob, request.getParameterMap());
        // Step.2 AutoPoi 匯出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        List<SysQuartzJob> pageList = quartzJobService.list(queryWrapper);
        // 匯出檔名稱
        mv.addObject(NormalExcelConstants.FILE_NAME, "定時任務列表");
        mv.addObject(NormalExcelConstants.CLASS, SysQuartzJob.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("定時任務列表資料", "匯出人:Jeecg", "匯出資訊"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通過excel匯入資料
     * 
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 獲取上傳檔案物件
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<SysQuartzJob> listSysQuartzJobs = ExcelImportUtil.importExcel(file.getInputStream(), SysQuartzJob.class, params);
                for (SysQuartzJob sysQuartzJobExcel : listSysQuartzJobs) {
                    quartzJobService.save(sysQuartzJobExcel);
                }
                return Result.ok("檔案匯入成功!資料行數:" + listSysQuartzJobs.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("檔案匯入失敗!");
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.error("檔案匯入失敗!");
    }
}