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("文件导入失败!");
    }
}

 7、job定时任务样例

package org.jeecg.modules.quartz.job;

import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import lombok.extern.slf4j.Slf4j;

/**
 * 示例不带参定时任务
 * 
 * @Author Scott
 */
@Slf4j
public class SampleJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        log.info(String.format(" Jeecg-Boot 普通定时任务 SampleJob !  时间:" + DateUtils.getTimestamp()));
    }
}

 

posted @ 2022-03-02 22:36  JackGIS  阅读(499)  评论(0编辑  收藏  举报