一、配置spring-scheduler.xml啓動任務後由這個任務去掃描數據庫,進行動態任務操作
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!--開啓一個任務掃描任務表動態創建管理等-->
<bean id="quartzJobManager" class="com.task.job.QuartzJobManager"/>
<!-- 定時任務自動創建任務 -->
<bean id="arrageScheduleJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="quartzJobManager"/>
<property name="targetMethod" value="arrageScheduleJob"/>
</bean>
<bean id="arrageScheduleJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail">
<ref bean="arrageScheduleJob"/>
</property>
<property name="cronExpression">
<value>0 */1 * * * ?</value>
</property>
</bean>
<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="arrageScheduleJobTrigger"/>
</list>
</property>
<property name="taskExecutor" ref="executor"/>
</bean>
<bean id="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10"/>
<property name="maxPoolSize" value="100"/>
<property name="queueCapacity" value="500"/>
</bean>
</beans>
spring-context.xml
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--掃描service-->
<context:component-scan base-package="com.task.service.impl"/>
<!-- 定時任務 -->
<import resource="spring-scheduler.xml"/>
</beans>
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!--是一種簡寫形式,完全可以手動配置替代這種簡寫形式,簡寫形式可以讓初學都快速應用默認配置方案。
會自動註冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個bean,
是spring MVC爲@Controllers分發請求所必須的。
並提供了:數據綁定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,讀寫XML的支持(JAXB),讀寫JSON的支持(Jackson)。-->
<mvc:annotation-driven/>
<!--掃描controller-->
<context:component-scan base-package="com.task.controller"/>
<!-- 視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前綴 -->
<property name="prefix">
<value>/WEB-INF/JSP/</value>
</property>
<!-- 後綴 -->
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!-- spring mvc 上傳文件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:maxUploadSize="512000000" p:maxInMemorySize="512000000" p:defaultEncoding="UTF-8"/>
<mvc:default-servlet-handler/>
</beans>
pom.xml
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.task</groupId>
<artifactId>AutoTask</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>AutoTask Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>5.0.4.RELEASE</spring.version>
<quartz.version>2.3.0</quartz.version>
<sqlite.version>3.21.0.1</sqlite.version>
<fileupload.version>1.3.3</fileupload.version>
<slf4j.version>1.8.0-beta1</slf4j.version>
<jackson.version>2.9.4</jackson.version>
</properties>
<dependencies>
<!--SPRING依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!--文件上傳依賴-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${fileupload.version}</version>
</dependency>
<!--常用工具類,比如StringUtil-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<!--gson json工具類-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<!--定時任務依賴-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
<!--SQLLITE驅動-->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>${sqlite.version}</version>
</dependency>
<!--日誌依賴-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!--@ResponseBody 依賴-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<build>
<finalName>AutoTask</finalName>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.8.v20171121</version>
<configuration>
<webAppConfig>
<contextPath>/</contextPath>
<webInfIncludeJarPattern>.*/foo-[^/]*\.jar$|.*/classes/.*</webInfIncludeJarPattern>
</webAppConfig>
<httpConnector>
<port>9999</port>
<idleTimeout>10000</idleTimeout>
</httpConnector>
</configuration>
</plugin>
</plugins>
</build>
</project>
二、主要類
package com.task.job;
import java.io.Serializable;
/**
* 對應的表<schedule_job>
*/
public class ScheduleJob implements Serializable {
private static final long serialVersionUID = -6268330198581041868L;
private String jobId;//任務ID
private String jobName;//任務名稱
private String jobGroup;//任務分組
private int jobStatus;//任務狀態 0啓用 1禁用 2刪除
private String cronExpression;//任務運行時間表達式
private String description;//任務描述
private String targetObject;//任務類名
private String targetMethod;//任務方法名
private int isSpringBean;//是否是Spring中定義的Bean 0 是 1 不是
private String clazz;//如果isSpringBean = 1 需要設置全類名,測試CLAZZ字段需要配置
private int concurrent;// 是否併發 0啓用 1禁用
public String getJobId() {
return jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
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 int getJobStatus() {
return jobStatus;
}
public void setJobStatus(int jobStatus) {
this.jobStatus = jobStatus;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTargetObject() {
return targetObject;
}
public void setTargetObject(String targetObject) {
this.targetObject = targetObject;
}
public String getTargetMethod() {
return targetMethod;
}
public void setTargetMethod(String targetMethod) {
this.targetMethod = targetMethod;
}
public int getIsSpringBean() {
return isSpringBean;
}
public void setIsSpringBean(int isSpringBean) {
this.isSpringBean = isSpringBean;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public int getConcurrent() {
return concurrent;
}
public void setConcurrent(int concurrent) {
this.concurrent = concurrent;
}
@Override
public String toString() {
return "ScheduleJob{" +
"jobId='" + jobId + '\'' +
", jobName='" + jobName + '\'' +
", jobGroup='" + jobGroup + '\'' +
", jobStatus=" + jobStatus +
", cronExpression='" + cronExpression + '\'' +
", description='" + description + '\'' +
", targetObject='" + targetObject + '\'' +
", targetMethod='" + targetMethod + '\'' +
", isSpringBean=" + isSpringBean +
", clazz='" + clazz + '\'' +
", concurrent=" + concurrent +
'}';
}
}
package com.task.job;
import com.task.service.ScheduleJobService;
import com.task.util.SpringContextUtil;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import javax.annotation.Resource;
import java.util.List;
/**
* 動態生成定時任務
*/
public class QuartzJobManager {
private static final Logger log = LogManager.getLogger(QuartzJobManager.class);
@Resource
private Scheduler scheduler;
@Resource
private ScheduleJobService scheduleJobService;
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
/**
* <p>
* 掃描數據庫,查看是否有計劃任務的變動
* <p>
*
* @Date 2018年3月22日
* @author Adam.Fei
*/
public void arrageScheduleJob() {
try {
List<ScheduleJob> jobList = scheduleJobService.getScheduleJobs();
if (jobList.size() != 0) {
for (ScheduleJob job : jobList) {
//triggerKey 由名稱和分組組成,組中的名稱必須唯一
TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
// 獲取trigger(時間觸發器)
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 不存在,創建一個
if (null == trigger) {
createSheduler(scheduler, job);
} else {
// Trigger已存在,那麼更新相應的定時設置
updateScheduler(scheduler, job, triggerKey, trigger);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* <p>
* 更新相應的定時設置 根據job_status做相應的處理
* <p>
*
* @param scheduler 定時任務調度器
* @param job 定時任務數據
* @param triggerKey 定時任務key
* @param trigger 時間觸發器
* @throws SchedulerException
* @Date 2018年3月22日
* @author wlx
*/
private void updateScheduler(Scheduler scheduler, ScheduleJob job, TriggerKey triggerKey, CronTrigger trigger)
throws SchedulerException {
switch (job.getJobStatus()) {
case 0://啓用狀態
if (!trigger.getCronExpression().equalsIgnoreCase(job.getCronExpression())) {
// 表達式調度構建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
// 按新的cronExpression表達式重新構建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 按新的trigger重新設置job執行
scheduler.rescheduleJob(triggerKey, trigger);
log.info(job.getJobGroup() + "." + job.getJobName() + " 更新完畢,目前cron表達式爲:" + job.getCronExpression()
+ " isSpringBean:" + job.getIsSpringBean() + " concurrent: " + job.getConcurrent());
}
break;
case 1://停用狀態
scheduler.pauseTrigger(triggerKey);// 停止觸發器
scheduler.unscheduleJob(triggerKey);// 移除觸發器
scheduler.deleteJob(trigger.getJobKey());// 刪除任務
log.info(job.getJobGroup() + "." + job.getJobName() + "刪除完畢");
break;
default:
log.error(job.getJobStatus() + "狀態未處理!");
}
}
/**
* <p>
* 創建一個定時任務,並做安排
* <p>
*
* @param scheduler 定時任務調度器
* @param job 定時任務數據
* @throws Exception
* @Date 2018年3月22日
* @author wlx
*/
public void createSheduler(Scheduler scheduler, ScheduleJob job) throws Exception {
// 在工作狀態可用時,即job_status = 0 ,開始創建
if (job.getJobStatus() == 0) {
// 新建一個基於Spring的管理Job類
MethodInvokingJobDetailFactoryBean methodInvJobDetailFB = new MethodInvokingJobDetailFactoryBean();
// 設置Job名稱
methodInvJobDetailFB.setName(job.getJobName());
// 定義的任務類爲Spring的定義的Bean則調用 getBean方法
if (job.getIsSpringBean() == 0) {// 是Spring中定義的Bean
methodInvJobDetailFB.setTargetObject(SpringContextUtil.getApplicationContext().getBean(job.getTargetObject()));
} else {// 不是
Object object = Class.forName(job.getClazz()).newInstance();
capableBeanFactory.autowireBean(object);
methodInvJobDetailFB.setTargetObject(object);
}
// 設置任務方法
methodInvJobDetailFB.setTargetMethod(job.getTargetMethod());
// 將管理Job類提交到計劃管理類
methodInvJobDetailFB.afterPropertiesSet();
/** 併發設置 */
methodInvJobDetailFB.setConcurrent(job.getConcurrent() == 0 ? true : false);
JobDetail jobDetail = methodInvJobDetailFB.getObject();// 動態
jobDetail.getJobDataMap().put("scheduleJob", job);
// 表達式調度構建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
// 按新的cronExpression表達式構建一個新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup())
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);// 注入到管理類
log.info(job.getJobGroup() + "." + job.getJobName() + "創建完畢");
}
}
}
package com.task.service;
import com.task.job.ScheduleJob;
import java.util.List;
public interface ScheduleJobService {
List<ScheduleJob> getScheduleJobs();
}
package com.task.service.impl;
import com.task.job.ScheduleJob;
import com.task.service.ScheduleJobService;
import com.task.util.SqliteUtil;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.util.List;
@Service("scheduleJobService")
public class ScheduleJobServiceImpl implements ScheduleJobService {
public List<ScheduleJob> getScheduleJobs() {
Connection connection = SqliteUtil.getConnection();
SqliteUtil.initTable(connection);
List<ScheduleJob> list = SqliteUtil.getJobDate(connection);
SqliteUtil.closeConnection(connection);
return list;
}
}
三、源碼下載
https://download.csdn.net/download/w13511069150/10303711