在实际项目开发中,我们想在规定时间执行一些任务,所以会经常用到定时任务。当然定时任务有很多种,本文我来介绍下我在项目中用到的quartz定时任务,项目架构采用的是微服务,主要写Spring Boot集成Quartz详解。

一、开发环境

   MySql、Mybatis、PageHelper、Spring Boot、Quartz

二、pom.xml依赖

<dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>

三、application.properties配置

# 固定前缀org.quartz
# 定时任务开关,true-开  false-关
quartz.autoStartup=false
quartz.delaySeconds=10
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.scheduler.wrapJobExecutionInUserTransaction=false
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
# 并发个数
org.quartz.threadPool.threadCount=10
# 优先级
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
org.quartz.jobStore.misfireThreshold=5000
# 默认存储在内存中
#org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
#持久化
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.dataSource=qzDS
org.quartz.dataSource.qzDS.maxConnections=10

四、quartzConfig配置

package com.fintech.modules.base.quartz;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;

/**
 * @author lc
 * @date: 2017/12/4 15:03
 * @description: quartz配置加载类
 */
@Configuration
public class QuartzConfig {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${quartz.autoStartup}")
    private Boolean autoStartup;

    @Value("${quartz.delaySeconds}")
    private Integer delaySeconds;

    @Value("${org.quartz.scheduler.instanceName}")
    private String schedulerInstanceName;

    @Value("${org.quartz.scheduler.rmi.export}")
    private String schedulerRmiExport;

    @Value("${org.quartz.scheduler.rmi.proxy}")
    private String schedulerRmiProxy;

    @Value("${org.quartz.scheduler.wrapJobExecutionInUserTransaction}")
    private String schedulerWrapJobExecutionInUserTransaction;

    @Value("${org.quartz.threadPool.class}")
    private String threadPoolClass;

    @Value("${org.quartz.threadPool.threadCount}")
    private String threadPoolThreadCount;

    @Value("${org.quartz.threadPool.threadPriority}")
    private String threadPoolThreadPriority;

    @Value("${org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread}")
    private String threadPoolThreadsInheritContextClassLoaderOfInitializingThread;

    @Value("${org.quartz.jobStore.misfireThreshold}")
    private String jobStoreMisfireThreshold;

    @Value("${org.quartz.jobStore.driverDelegateClass}")
    private String jobStoreDriverDelegateClass;

    @Value("${org.quartz.jobStore.class}")
    private String jobStoreClass;

    @Value("${org.quartz.jobStore.tablePrefix}")
    private String jobStoreTablePrefix;

    @Value("${org.quartz.jobStore.dataSource}")
    private String jobStoreDataSource;

    /*@Value("${org.quartz.dataSource.qzDS.maxConnections}")
    private String dataSourceMaxConnections;

    @Value("${spring.datasource.driver-class-name}")
    private String dataSourceDriver;

    @Value("${spring.datasource.url}")
    private String dataSourceURL;

    @Value("${spring.datasource.username}")
    private String dataSourceUser;

    @Value("${spring.datasource.password}")
    private String dataSourcePassword;*/

    @Bean
    public Properties quartzProperties() throws IOException {
        Properties quartzProperties = new Properties();
        quartzProperties.setProperty("org.quartz.scheduler.instanceName", schedulerInstanceName);
        quartzProperties.setProperty("org.quartz.scheduler.rmi.export", schedulerRmiExport);
        quartzProperties.setProperty("org.quartz.scheduler.rmi.proxy", schedulerRmiProxy);
        quartzProperties.setProperty("org.quartz.scheduler.wrapJobExecutionInUserTransaction", schedulerWrapJobExecutionInUserTransaction);
        quartzProperties.setProperty("org.quartz.threadPool.class", threadPoolClass);
        quartzProperties.setProperty("org.quartz.threadPool.threadCount", threadPoolThreadCount);
        quartzProperties.setProperty("org.quartz.threadPool.threadPriority", threadPoolThreadPriority);
        quartzProperties.setProperty("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", threadPoolThreadsInheritContextClassLoaderOfInitializingThread);
        quartzProperties.setProperty("org.quartz.jobStore.misfireThreshold", jobStoreMisfireThreshold);
        quartzProperties.setProperty("org.quartz.jobStore.class", jobStoreClass);
        quartzProperties.setProperty("org.quartz.jobStore.driverDelegateClass", jobStoreDriverDelegateClass);
        quartzProperties.setProperty("org.quartz.jobStore.tablePrefix", jobStoreTablePrefix);
        quartzProperties.setProperty("org.quartz.jobStore.dataSource", jobStoreDataSource);
        /*quartzProperties.setProperty("org.quartz.dataSource.qzDS.maxConnections", dataSourceMaxConnections);
        quartzProperties.setProperty("org.quartz.dataSource.qzDS.driver", dataSourceDriver);
        quartzProperties.setProperty("org.quartz.dataSource.qzDS.URL", dataSourceURL);
        quartzProperties.setProperty("org.quartz.dataSource.qzDS.user", dataSourceUser);
        quartzProperties.setProperty("org.quartz.dataSource.qzDS.password", dataSourcePassword);*/

        return quartzProperties;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) throws IOException {
        logger.info("开始配置quartz定时任务");
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        // 加载quartz数据源配置
        factory.setQuartzProperties(quartzProperties());
        // 加载数据源
        factory.setDataSource(dataSource);
        // 将spring上下文放入quartz中, 用于在job执行时获取注入bean
        factory.setApplicationContextSchedulerContextKey("applicationContextKey");

        factory.setOverwriteExistingJobs(true);

        if(autoStartup) {
            // 延时启动
            if(delaySeconds > 0) {
                factory.setStartupDelay(delaySeconds);
            }
            logger.info("quartz开启自动启动定时任务, 延时{}s启动", delaySeconds);
        } else {
            factory.setAutoStartup(false);
            logger.warn("quartz未开启自动启动定时任务");
        }

        logger.info("quartz定时任务配置成功");
        return factory;
    }
}

五、实现

1、新建Java Bean
package com.fintech.modules.quartzjobmanage.dto;

/**
 * @Description: 定时任务bean
 * @author lc
 * @date 2018年5月29日
 */
public class JobAndTriggerDTO {
	/**
	 * 任务名称
	 */
	private String jobName;
	
	/**
	 * 任务所在组
	 */
	private String jobGroup;
	
	/**
	 * 任务类名
	 */
	private String jobClassName;
	
	/**
	 * 触发器名称
	 */
	private String triggerName;
	
	/**
	 * 触发器所在组
	 */
	private String triggerGroup;
	
	/**
	 * 表达式
	 */
	private String cronExpression;
	
	/**
	 * 时区
	 */
	private String timeZoneId;
	
	/**
	 * 状态
	 */
	private String triggerStart;
	
	/**
	 * 创建时间
	 */
	private String startTime;
	
	/**
	 * 上次执行时间
	 */
	private String prevFireTime;
	
	/**
	 * 下次执行时间
	 */
	private String nextFireTime;
	
	public String getTriggerStart() {
		return triggerStart;
	}
	public void setTriggerStart(String triggerStart) {
		this.triggerStart = triggerStart;
	}
	public String getStartTime() {
		return startTime;
	}
	public void setStartTime(String startTime) {
		this.startTime = startTime;
	}
	public String getPrevFireTime() {
		return prevFireTime;
	}
	public void setPrevFireTime(String prevFireTime) {
		this.prevFireTime = prevFireTime;
	}
	public String getNextFireTime() {
		return nextFireTime;
	}
	public void setNextFireTime(String nextFireTime) {
		this.nextFireTime = nextFireTime;
	}
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
	public String getJobGroup() {
		return jobGroup;
	}
	public void setJobGroup(String jobGroup) {
		this.jobGroup = jobGroup;
	}
	public String getJobClassName() {
		return jobClassName;
	}
	public void setJobClassName(String jobClassName) {
		this.jobClassName = jobClassName;
	}
	public String getTriggerName() {
		return triggerName;
	}
	public void setTriggerName(String triggerName) {
		this.triggerName = triggerName;
	}
	public String getTriggerGroup() {
		return triggerGroup;
	}
	public void setTriggerGroup(String triggerGroup) {
		this.triggerGroup = triggerGroup;
	}
	public String getCronExpression() {
		return cronExpression;
	}
	public void setCronExpression(String cronExpression) {
		this.cronExpression = cronExpression;
	}
	public String getTimeZoneId() {
		return timeZoneId;
	}
	public void setTimeZoneId(String timeZoneId) {
		this.timeZoneId = timeZoneId;
	}
}
2、xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >  
<mapper namespace="com.fintech.modules.quartzjobmanage.dao.JobAndTriggerMapper">  
    
<select id="getJobAndTriggerDetails" resultType="com.fintech.modules.quartzjobmanage.dto.JobAndTriggerDTO">
	SELECT
	  qrtz_job_details.JOB_NAME          AS jobName,
	  qrtz_job_details.JOB_GROUP         AS jobGroup,
	  qrtz_job_details.JOB_CLASS_NAME    AS jobClassName,
	  qrtz_triggers.TRIGGER_NAME         AS triggerName,
	  qrtz_triggers.TRIGGER_GROUP        AS triggerGroup,
	  qrtz_cron_triggers.CRON_EXPRESSION AS cronExpression,
	  qrtz_cron_triggers.TIME_ZONE_ID    AS timeZoneId,
	  qrtz_triggers.TRIGGER_STATE        AS triggerStart,
	  FROM_UNIXTIME(qrtz_triggers.START_TIME/1000) AS startTime,
	  FROM_UNIXTIME(qrtz_triggers.PREV_FIRE_TIME/1000) AS prevFireTime,
	  FROM_UNIXTIME(qrtz_triggers.NEXT_FIRE_TIME/1000) AS nextFireTime
	FROM qrtz_job_details
	  JOIN qrtz_triggers
	  JOIN qrtz_cron_triggers
	    ON qrtz_job_details.JOB_NAME = qrtz_triggers.JOB_NAME
	      AND qrtz_triggers.TRIGGER_NAME = qrtz_cron_triggers.TRIGGER_NAME
	      AND qrtz_triggers.TRIGGER_GROUP = qrtz_cron_triggers.TRIGGER_GROUP
 </select>
    
</mapper>
3、dao
package com.fintech.modules.quartzjobmanage.dao;

import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.fintech.modules.quartzjobmanage.dto.JobAndTriggerDTO;

/**
 * @Description: 定时任务dao
 * @author lc
 * @date 2018年5月29日
 */
@Mapper
public interface JobAndTriggerMapper {
	
	/**
	 * @Description: 查询定时任务信息
	 * @author lc
	 */
	public List<JobAndTriggerDTO> getJobAndTriggerDetails();
}
4、service
package com.fintech.modules.quartzjobmanage.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fintech.modules.quartzjobmanage.dao.JobAndTriggerMapper;
import com.fintech.modules.quartzjobmanage.dto.JobAndTriggerDTO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

/**
 * @Description: 定时任务service
 * @author lc
 * @date 2018年5月29日
 */
@Service
public class JobAndTriggerService{

	@Autowired
	private JobAndTriggerMapper jobAndTriggerMapper;
	
	/**
	 * @Description: 查询定时任务信息
	 * @author lc
	 */
	public PageInfo<JobAndTriggerDTO> getJobAndTriggerDetails(int pageNum, int pageSize) {
		PageHelper.startPage(pageNum, pageSize);
		List<JobAndTriggerDTO> list = jobAndTriggerMapper.getJobAndTriggerDetails();
		PageInfo<JobAndTriggerDTO> page = new PageInfo<JobAndTriggerDTO>(list);
		return page;
	}

}
5、controller
package com.fintech.modules.quartzjobmanage.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.fintech.modules.base.util.SmsException;
import com.fintech.modules.quartzjobmanage.dto.JobAndTriggerDTO;
import com.fintech.modules.quartzjobmanage.service.JobAndTriggerService;
import com.fintech.modules.sms.common.dto.LayuiResult;
import com.github.pagehelper.PageInfo;

/**
 * @author xujunqi
 * @date: 2017/12/9 15:24
 * @description: 定时任务配置控制类
 */
@RestController
@RequestMapping(value = "/quartzjob")
@Api(tags="定时任务配置控制类")
public class QuartzJobController {
    private static Logger logger = LoggerFactory.getLogger(QuartzJobController.class);

    @Autowired
    private Scheduler scheduler;
    @Autowired 
    private JobAndTriggerService jobAndTriggerService;
    
    @ApiOperation(value= "添加定时任务", notes= "添加定时任务")
    @PostMapping(value = "/addjob")
    public String addjobController(@RequestParam(value = "jobClassName") String jobClassName,
                                 @RequestParam(value = "jobGroupName") String jobGroupName,
                                 @RequestParam(value = "cronExpression") String cronExpression) throws Exception {
        addJob(jobClassName, jobGroupName, cronExpression);

        return "定时任务添加成功";
    }

    public void addJob(String jobClassName, String jobGroupName, String cronExpression) throws Exception {
        if(StringUtils.isBlank(jobGroupName)) {
            jobGroupName = Scheduler.DEFAULT_GROUP;
        }
        // 启动调度器
        scheduler.start();
        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName, jobGroupName).build();
        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
                .withSchedule(scheduleBuilder).build();
        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            logger.error("创建定时任务失败", e);
            throw new SmsException("创建定时任务失败");
        }
    }
    
/*    @ApiOperation(value= "根据条件查询定时任务", notes= "根据条件查询定时任务")
    @PostMapping(value = "/queryjob")
    public String queryjob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobPause(jobClassName, jobGroupName);

        return "定时任务暂停成功";
    }*/

    @ApiOperation(value= "根据条件暂停定时任务", notes= "根据条件暂停定时任务")
    @PostMapping(value = "/pausejob")
    public String pausejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobPause(jobClassName, jobGroupName);

        return "定时任务暂停成功";
    }

    public void jobPause(String jobClassName, String jobGroupName) throws Exception {
        if(StringUtils.isBlank(jobGroupName)) {
            jobGroupName = Scheduler.DEFAULT_GROUP;
        }
        // 通过SchedulerFactory获取一个调度器实例
        scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
    }

    @ApiOperation(value= "根据条件恢复定时任务", notes= "根据条件恢复定时任务")
    @PostMapping(value = "/resumejob")
    public String resumejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobresume(jobClassName, jobGroupName);

        return "定时任务恢复成功";
    }

    public void jobresume(String jobClassName, String jobGroupName) throws Exception {
        if(StringUtils.isBlank(jobGroupName)) {
            jobGroupName = Scheduler.DEFAULT_GROUP;
        }
        // 通过SchedulerFactory获取一个调度器实例
        scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
    }

    @ApiOperation(value= "根据条件定时任务", notes= "根据条件定时任务")
    @PostMapping(value = "/reschedulejob")
    public String rescheduleJob(@RequestParam(value = "jobClassName") String jobClassName,
                              @RequestParam(value = "jobGroupName") String jobGroupName,
                              @RequestParam(value = "cronExpression") String cronExpression) throws Exception {
        jobreschedule(jobClassName, jobGroupName, cronExpression);

        return "定时任务重新调度成功";
    }

    public void jobreschedule(String jobClassName, String jobGroupName, String cronExpression) throws Exception {
        if(StringUtils.isBlank(jobGroupName)) {
            jobGroupName = Scheduler.DEFAULT_GROUP;
        }

        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            logger.error("更新定时任务失败", e);
            throw new SmsException("更新定时任务失败");
        }
    }

    @ApiOperation(value= "根据条件删除定时任务", notes= "根据条件删除定时任务")
    @PostMapping(value = "/deletejob")
    public String deletejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobdelete(jobClassName, jobGroupName);

        return "定时任务删除成功";
    }

    public void jobdelete(String jobClassName, String jobGroupName) throws Exception {
        if(StringUtils.isBlank(jobGroupName)) {
            jobGroupName = Scheduler.DEFAULT_GROUP;
        }

        // 通过SchedulerFactory获取一个调度器实例
        scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));//停止触发器  
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));//移除触发器 
        scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));//删除任务  
    }

    /**
     * @Description: 定时任务管理
     * @author lc
     */
    @ApiOperation(value= "定时任务管理", notes= "根据条件管理定时任务")
    @GetMapping(value = "/queryjob")
    public Map<String, Object> queryjob(@RequestParam(value = "pageNum") Integer pageNum, @RequestParam(value = "pageSize") Integer pageSize) {
        PageInfo<JobAndTriggerDTO> jobAndTrigger = jobAndTriggerService.getJobAndTriggerDetails(pageNum, pageSize);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("JobAndTrigger", jobAndTrigger);
        map.put("number", jobAndTrigger.getTotal());
        return map;
    }
    
    /**
     * @Description: 查询定时任务
     * @author lc
     */
    @ApiOperation(value= "查询定时任务", notes= "根据条件查询定时任务")
    @GetMapping(value = "/queryJobList")
    public LayuiResult queryJobList(@RequestParam Map<String, Object> paramMap) {
        PageInfo<JobAndTriggerDTO> list = jobAndTriggerService.getJobAndTriggerDetails(Integer.parseInt(paramMap.get("page").toString()), Integer.parseInt(paramMap.get("limit").toString()));
        return LayuiResult.data(list.getTotal(), list.getList());
    }

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

}
6、设置定时任务例子
package com.fintech.modules.base.quartzjobs;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import com.fintech.modules.sms.smsreport.service.SmsLogStatusReportService;

/**
 * @Description: 每分钟/短信报文统计发送状态
 * @author lc
 * @date 2018年4月10日
 * 每2分钟统计一次
 */
@Component
public class SmsReportStatisJob extends QuartzJobBean {
    private static final long serialVersionUID = 1L;
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
    	logger.info("开始执行-定时短信发送报文统计:{}");
        try {
            SchedulerContext cont = context.getScheduler().getContext();
            ApplicationContext appCtx = (ApplicationContext) cont.get("applicationContextKey");
            // 调用具体sercive业务代码
            SmsLogStatusReportService service = appCtx.getBean(SmsLogStatusReportService.class);
            service.smsReportStatis();
        } catch (Exception e) {
            logger.error("每分钟/短信报文跑批统计发送状态异常!{}", e);
        } 
        logger.info("执行结束-定时短信发送报文统计:{}");
    }
}

六、页面管理

在Spring Boot的工程中,静态页面可以放在资源文件static目录下,controller已经写好了,页面完全按照自己的需求去实现即可,下面是我拷贝别人的管理页面,这里贴一下代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>定时任务</title>
<link rel="stylesheet"
	href="https://unpkg.com/element-ui@2.0.5/lib/theme-chalk/index.css">
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="http://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.js"></script>
<script src="https://unpkg.com/element-ui@2.0.5/lib/index.js"></script>

<style>
#top {
	background: #20A0FF;
	padding: 5px;
	overflow: hidden
}
</style>
</head>
<body>
	<div id="test">
		<div id="top">
			<el-button type="text" @click="search" style="color:white">查询</el-button>
			<el-button type="text" @click="handleadd" style="color:white">添加</el-button>
			</span>
		</div>
		<br />
		<div style="margin-top: 15px">
			<el-table ref="testTable" :data="tableData" style="width:100%" border>
			<el-table-column prop="jobName" label="任务名称" sortable
				show-overflow-tooltip> </el-table-column> <el-table-column
				prop="jobGroup" label="任务所在组" sortable> </el-table-column> <el-table-column
				prop="jobClassName" label="任务类名" sortable> </el-table-column> <el-table-column
				prop="triggerName" label="触发器名称" sortable> </el-table-column> <el-table-column
				prop="triggerGroup" label="触发器所在组" sortable> </el-table-column> <el-table-column
				prop="cronExpression" label="表达式" sortable> </el-table-column> <el-table-column
				prop="timeZoneId" label="时区" sortable> </el-table-column> <el-table-column
				label="操作" width="300"> <template scope="scope">
			<el-button size="small" type="warning"
				@click="handlePause(scope.$index, scope.row)">暂停</el-button> <el-button
				size="small" type="info"
				@click="handleResume(scope.$index, scope.row)">恢复</el-button> <el-button
				size="small" type="danger"
				@click="handleDelete(scope.$index, scope.row)">删除</el-button> <el-button
				size="small" type="success"
				@click="handleUpdate(scope.$index, scope.row)">修改</el-button> </template> </el-table-column> </el-table>

			<div align="center">
				<el-pagination @size-change="handleSizeChange"
					@current-change="handleCurrentChange" :current-page="currentPage"
					:page-sizes="[10, 20, 30, 40]" :page-size="pagesize"
					layout="total, sizes, prev, pager, next, jumper"
					:total="totalCount"> </el-pagination>
			</div>
		</div>

		<el-dialog title="添加任务" :visible.sync="dialogFormVisible">
		<el-form :model="form"> <el-form-item label="任务名称"
			label-width="120px" style="width:35%"> <el-input
			v-model="form.jobName" auto-complete="off"></el-input> </el-form-item> <el-form-item
			label="任务分组" label-width="120px" style="width:35%"> <el-input
			v-model="form.jobGroup" auto-complete="off"></el-input> </el-form-item> <el-form-item
			label="表达式" label-width="120px" style="width:35%"> <el-input
			v-model="form.cronExpression" auto-complete="off"></el-input> </el-form-item> </el-form>
		<div slot="footer" class="dialog-footer">
			<el-button @click="dialogFormVisible = false">取 消</el-button>
			<el-button type="primary" @click="add">确 定</el-button>
		</div>
		</el-dialog>

		<el-dialog title="修改任务" :visible.sync="updateFormVisible">
		<el-form :model="updateform"> <el-form-item label="表达式"
			label-width="120px" style="width:35%"> <el-input
			v-model="updateform.cronExpression" auto-complete="off"></el-input> </el-form-item>
		</el-form>
		<div slot="footer" class="dialog-footer">
			<el-button @click="updateFormVisible = false">取 消</el-button>
			<el-button type="primary" @click="update">确 定</el-button>
		</div>
		</el-dialog>
	</div>

	<footer align="center">
		<p>&copy; Quartz 任务管理</p>
	</footer>
	<script>
	var vue = new Vue({			
			el:"#test",
		    data: {		  
		    	//表格当前页数据
		    	tableData: [],
		        //请求的URL
		        url:'quartzjob/queryjob',
		        //默认每页数据量
		        pagesize: 10,		        
		        //当前页码
		        currentPage: 1,
		        //查询的页码
		        start: 1,
		        //默认数据总数
		        totalCount: 0,
		        //添加对话框默认可见性
		        dialogFormVisible: false,
		        //修改对话框默认可见性
		        updateFormVisible: false,
		        //提交的表单
		        form: {
		        	jobName: '',
		        	jobGroup: '',
		        	cronExpression: '',
		          },
		        updateform: {
		        	jobName: '',
		        	jobGroup: '',
		        	cronExpression: '',
		        },
		    },
		    methods: {
		        //从服务器读取数据
				loadData: function(pageNum, pageSize){					
					this.$http.get('quartzjob/queryjob?' + 'pageNum=' +  pageNum + '&pageSize=' + pageSize).then(function(res){
						console.log(res)
                		this.tableData = res.body.JobAndTrigger.list;
                		this.totalCount = res.body.number;
                	},function(){
                  		console.log('failed');
                	});					
				},			    		        
		        //单行删除
			    handleDelete: function(index, row) {
					this.$http.post('quartzjob/deletejob',{"jobClassName":row.jobName,"jobGroupName":row.jobGroup},{emulateJSON: true}).then(function(res){
						this.loadData( this.currentPage, this.pagesize);
		            },function(){
		                console.log('failed');
		            });
		        },
		        //暂停任务
		        handlePause: function(index, row){
		        	this.$http.post('quartzjob/pausejob',{"jobClassName":row.jobName,"jobGroupName":row.jobGroup},{emulateJSON: true}).then(function(res){
						this.loadData( this.currentPage, this.pagesize);
		            },function(){
		                console.log('failed');
		            });
		        },
		        //恢复任务
		        handleResume: function(index, row){
		        	this.$http.post('quartzjob/resumejob',{"jobClassName":row.jobName,"jobGroupName":row.jobGroup},{emulateJSON: true}).then(function(res){
						this.loadData( this.currentPage, this.pagesize);
		            },function(){
		                console.log('failed');
		            });
		        },
		        //搜索
		        search: function(){
		        	this.loadData(this.currentPage, this.pagesize);
		        },
		        //弹出对话框
		        handleadd: function(){		                
		            this.dialogFormVisible = true;	              
		        },
		        //添加
		        add: function(){
		        	this.$http.post('quartzjob/addjob',{"jobClassName":this.form.jobName,"jobGroupName":this.form.jobGroup,"cronExpression":this.form.cronExpression},{emulateJSON: true}).then(function(res){
        				this.loadData(this.currentPage, this.pagesize);
        				this.dialogFormVisible = false;
                    },function(){
                        console.log('failed');
                    });
		        },
		        //更新
		        handleUpdate: function(index, row){
		        	console.log(row)
		        	this.updateFormVisible = true;
		        	this.updateform.jobName = row.jobClassName;
		        	this.updateform.jobGroup = row.jobGroup;
		        },
		        //更新任务
		        update: function(){
		        	this.$http.post
		        	('quartzjob/reschedulejob',
		        			{"jobClassName":this.updateform.jobName,
		        			 "jobGroupName":this.updateform.jobGroup,
		        			 "cronExpression":this.updateform.cronExpression
		        			 },{emulateJSON: true}
		        	).then(function(res){
		        		this.loadData(this.currentPage, this.pagesize);
        				this.updateFormVisible = false;
		        	},function(){
                        console.log('failed');
                    });
		        },
		        //每页显示数据量变更
		        handleSizeChange: function(val) {
		            this.pagesize = val;
		            this.loadData(this.currentPage, this.pagesize);
		        },
		        //页码变更
		        handleCurrentChange: function(val) {
		            this.currentPage = val;
		            this.loadData(this.currentPage, this.pagesize);
		        },	      
		    },	    
		  });
		  //载入数据
    	  vue.loadData(vue.currentPage, vue.pagesize);
	</script>
</body>
</html>

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐