您的位置:首页 > 编程语言 > Java开发

spring4和quartz2.x整合,对任务做动态操作(增删改查)

2017-10-15 16:12 429 查看
quartz 1.x版本和quartz2.x版本变化有点大,所以开始使用quartz时要注意版本

项目结构如下



本demo 的设计思想是对定时任务的增删改查等,需要通过相关的反射知识,及通过任务描述类中group和trigger来得到相关的job

项目使用maven jar如下

        

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

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version> 4.1.2.RELEASE  </version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.39</version>
</dependency>


写一个操作定时任务的service 接口

package com.quartz.service;

import java.util.List;

import org.quartz.Trigger;

import com.quartz.ScheduleTask;

public interface TaskService {
/**
* 获取所有的定时任务
* @return
*/
public List<ScheduleTask> getAllTask();
/**
* 获取触发器
* @param trigger 触发器名称(这里相当于方法名)
* @param group 任务组名称(这里相当于job所在的类名称)
* @return
*/
public Trigger getTrigger(String trigger,String group);
/**
* 添加一个新的定时任务
* @param task
* @return
*/
public ScheduleTask addTask(ScheduleTask task);
/**
* 重启定时任务
* @param task
* @return
*/
public ScheduleTask reStartTask(ScheduleTask task);
/**
* 删除指定定时任务
* @param task
* @return
*/
public ScheduleTask deleteTask(ScheduleTask task);
/**
* 暂停任务
* @param task
* @return
*/
public ScheduleTask pauseTask(ScheduleTask task);
/**
* 恢复任务
* @param task
* @return
*/
public ScheduleTask resumeTask(ScheduleTask task);
/**
* 批量删除定时任务
*/
public void deleteTasks(List<ScheduleTask> scheduleTasks);
/**
* 暂停所有的定时任务
*/
public void pauseAllTask();

}
实现类如下:

package com.quartz.service.impl;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import com.quartz.ScheduleTask;
import com.quartz.job.MyJob2;
import com.quartz.service.TaskService;

@Service("taskService")
public class TaskServiceImpl implements TaskService {

private ConcurrentHashMap<String, ScheduleTask> allTask = new ConcurrentHashMap<String, ScheduleTask>();

@Autowired
private SchedulerFactoryBean schedulerFactoryBean;

public List<ScheduleTask> getAllTask() {
List<ScheduleTask> list = new ArrayList();
list.addAll(allTask.values());
return list;
}

public CronTrigger getTrigger(String trigger, String group) {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
CronTrigger cronTrigger = null;
try {
cronTrigger = (CronTrigger) scheduler.getTrigger(new TriggerKey(
trigger, group));
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return cronTrigger;
}

public ScheduleTask addTask(ScheduleTask task) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobDetail jobDetail = JobBuilder.newJob(MyJob2.class)
.withIdentity(task.getName(), task.getGroup()).build();
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity(task.getTrigger(), task.getGroup())
.startNow()
.withSchedule(
CronScheduleBuilder.cronSchedule(task
.getExpression())).build();
System.out.println(trigger.getKey());
Class<?> classzz = Class.forName(task.getGroup());
Class<?>[] c = new Class<?>[task.getParam().length];
for (int i = 0; i < task.getParam().length; i++) {
c[i] = task.getParam()[i].getClass();
}
Method method = classzz.getMethod(task.getTrigger(), c);
JobDataMap jobDataMap = trigger.getJobDataMap();
jobDataMap.put(MyJob2.JOB_NAME, task.getName());
jobDataMap.put(MyJob2.JOB_GROUP, classzz);
jobDataMap.put(MyJob2.JOB_TRIGGER, method);
jobDataMap.put(MyJob2.JOB_TRIGGER_PARAM, task.getParam());
scheduler.scheduleJob(jobDetail, trigger);
if (scheduler.isStarted()) {
scheduler.start();
}
if (!allTask.containsKey(task.getId())) {
allTask.put(task.getId(), task);
}
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return task;
}

public ScheduleTask reStartTask(ScheduleTask task) {
try {
CronTrigger cronTrigger = getTrigger(task.getTrigger(),
task.getGroup());
Scheduler scheduler = schedulerFactoryBean.getScheduler();
cronTrigger = cronTrigger
.getTriggerBuilder()
.withIdentity(
new TriggerKey(task.getTrigger(), task.getGroup()))
.withSchedule(
CronScheduleBuilder.cronSchedule(task
.getExpression())).build();

// 按新的trigger重新设置job执行

scheduler.rescheduleJob(
new
4000
TriggerKey(task.getTrigger(), task.getGroup()),
cronTrigger);
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// 下方可以做一些更新数据库中任务的操作

return task;
}

public ScheduleTask deleteTask(ScheduleTask task) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jobKey = new JobKey(task.getName(), task.getGroup());
scheduler.deleteJob(jobKey);
} catch (SchedulerException e) {

e.printStackTrace();
}
return task;
}

public ScheduleTask pauseTask(ScheduleTask task) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jobKey = new JobKey(task.getName(), task.getGroup());
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return task;
}

public ScheduleTask resumeTask(ScheduleTask task) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
JobKey jobKey = new JobKey(task.getName(), task.getGroup());
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return task;
}

public void deleteTasks(List<ScheduleTask> scheduleTasks) {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
List<JobKey> jobKeys = new ArrayList<JobKey>();
JobKey jobKey;
for (ScheduleTask scheduleTask : scheduleTasks) {
jobKey = new JobKey(scheduleTask.getName(),
scheduleTask.getGroup());
jobKeys.add(jobKey);
}
scheduler.deleteJobs(jobKeys);
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

public void pauseAllTask() {
try {
Scheduler scheduler = schedulerFactoryBean.getScheduler();
scheduler.pauseAll();
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
本项目中打算将所有的定时任务都管理起来,包括@Scheduled注解的任务,需要将配置文件中<task:annotation-driven/>去掉,我们手动的启动注解任务

ManagerJob.java 如下

package com.quartz.job;

import java.lang.reflect.Method;

import javax.annotation.Resource;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.quartz.ScheduleTask;
import com.quartz.service.TaskService;
import com.quartz.util.SnowflakeIdWorker;
@Component
public class ManagerJob implements ApplicationListener<ContextRefreshedEvent> {

@Resource
private TaskService taskService;

public void onApplicationEvent(ContextRefreshedEvent arg0) {
ApplicationContext applicationContext = arg0.getApplicationContext();
String[] beans=applicationContext.getBeanDefinitionNames();
for(String bean :beans){
Class<?> class1 = applicationContext.getBean(bean).getClass();
Method[] methods = class1.getMethods();
for(Method method:methods){
if(method.isAnnotationPresent(Scheduled.class)){
Scheduled annotation = method.getAnnotation(Scheduled.class);
ScheduleTask scheduleTask=new ScheduleTask();
scheduleTask.setGroup(class1.getName());
scheduleTask.setTrigger(method.getName());
scheduleTask.setId(String.valueOf(SnowflakeIdWorker.getInstance().nextId()));
scheduleTask.setExpression(annotation.cron());
scheduleTask.setParam(new Object[]{});
scheduleTask.setName("task2");
taskService.addTask(scheduleTask);
}
}
}
}

}
自定义MyJob,不实现Job接口的

package com.quartz.job;

public class MyJob {

public void execute() {
System.out.println("---------执行----MyJob-----");
}

public void findUserName(String name,Integer age){
System.out.println("欢迎"+age+"岁的"+name+"光临");
}

}
代理MyJob2 实现Job接口的

package com.quartz.job;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob2 implements Job {

public static final String JOB_NAME="job_name";
public static final String JOB_GROUP="job_group";
public static final String JOB_TRIGGER="job_trigger";
public static final String JOB_TRIGGER_PARAM="job_trigger_param";
public void execute(JobExecutionContext context)
throws JobExecutionException {
try {
System.out.println("----执行------"+new SimpleDateFormat("yyyy-MM-dd HH:mm:dd:ss").format(new Date()));
JobDataMap jobDataMap = context.getTrigger().getJobDataMap();
String jobName=(String) jobDataMap.get(MyJob2.JOB_NAME);
Class<?> classzz=(Class<?>) jobDataMap.get(MyJob2.JOB_GROUP);
Method method=(Method) jobDataMap.get(MyJob2.JOB_TRIGGER);
Object[] objects=(Object[]) jobDataMap.get(MyJob2.JOB_TRIGGER_PARAM);
method.invoke(classzz.newInstance(), objects);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
MyJob3 通过注解实现的定时任务

package com.quartz.job;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MyJob3 {

@Scheduled(cron="0/5 * * * * ?")
public void execute(){
System.out.println("------执行注解实现的定时任务-----");
}
}


定时任务的描述类ScheduleTask

package com.quartz;
import java.io.Serializable;
public class ScheduleTask implements Serializable{

/**
*
*/
private static final long serialVersionUID = -6696079243640708701L;

private String id;//任务Id
private String name;//任务名
private String group;//任务所在类全名称
private String trigger;//任务执行的方法名
private String expression;//任务频率 和cron语法保持一致
private Object[] param;//执行任务方法的参数
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getTrigger() {
return trigger;
}
public void setTrigger(String trigger) {
this.trigger = trigger;
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
public Object[] getParam() {
return param;
}
public void setParam(Object[] param) {
this.param = param;
}
}


spring-quartz2配置文件

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:task="http://www.springframework.org/schema/task"
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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd"> 
<context:component-scan base-package="com.quartz"></context:component-scan>
<!-- <task:annotation-driven/> -->
<!-- ======================== 调度工厂 ======================== -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
</bean>
</beans>


测试类

package com.quartz.test;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.quartz.ScheduleTask;
import com.quartz.service.TaskService;

@ContextConfiguration(locations={"classpath:spring-quartz2.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class QuartzTest {

@Autowired
private TaskService taskService;

@Test
public void addTask() throws InterruptedException{
System.out.println("test--------start----------");
ScheduleTask task=new ScheduleTask();
task.setExpression("0/5 * * * * ?");
task.setId("001");
task.setGroup("com.quartz.job.MyJob");
task.setTrigger("findUserName");
task.setName("task1");
task.setParam(new Object[]{"zyc",22});
List<ScheduleTask> list=taskService.getAllTask();
System.out.println(JSON.toJSONString(list));
//		taskService.addTask(task);
//		Thread.sleep(1000*20);
//		System.out.println("重启定时任务");
//		task.setExpression("0/10 * * * * ?");
//		taskService.reStartTask(task);
while(true){}
}
}


完成以上还需要添加log4j.properties 配置文件,测试使用

可使用如下,或者网上自己搜

log4j.rootLogger=DEBUG,Console,File

log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%p][%d{HH\:mm\:ss,SSS}][%c]%m%n

log4j.appender.File=org.apache.log4j.RollingFileAppender
log4j.appender.File.File=quart.log
log4j.appender.File.MaxFileSize=10MB
log4j.appender.File.Threshold=ALL
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n

log4j.logger.org.quartz=WARN,Console,File
log4j.logger.org.activiti=WARN,Console,File
log4j.logger.org.apache=WARN,Console,File
log4j.logger.org.mybatis=WARN,Console,File
log4j.logger.net.sf.ehcache=WARN,Console,File
log4j.logger.org.springframework=WARN,Console,File
log4j.logger.org.springframework.jdbc.core.JdbcTemplate=debug,Console,File
log4j.logger.freemarker=WARN,Console,File

SnowflakeIdWorker 是id生成器id生成器使用的是雪花算法如下 可百度分布式id生成器
package com.quartz.util;
public class SnowflakeIdWorker {

private static SnowflakeIdWorker SnowflakeIdWorker=new SnowflakeIdWorker();
//声明私有构造函数
private SnowflakeIdWorker(){

}
// ==============================Fields===========================================
/** 开始时间截 (2015-01-01) */
private final long twepoch = 1420041600000L;

/** 机器id所占的位数 */
private final long workerIdBits = 5L;

/** 数据标识id所占的位数 */
private final long datacenterIdBits = 5L;

/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

/** 支持的最大数据标识id,结果是31 */
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

/** 序列在id中占的位数 */
private final long sequenceBits = 12L;

/** 机器ID向左移12位 */
private final long workerIdShift = sequenceBits;

/** 数据标识id向左移17位(12+5) */
private final long datacenterIdShift = sequenceBits + workerIdBits;

/** 时间截向左移22位(5+5+12) */
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
private final long sequenceMask = -1L ^ (-1L << sequenceBits);

/** 工作机器ID(0~31) */
private long workerId;

/** 数据中心ID(0~31) */
private long datacenterId;

/** 毫秒内序列(0~4095) */
private long sequence = 0L;

/** 上次生成ID的时间截 */
private long lastTimestamp = -1L;

//==============================Constructors=====================================
/**
* 构造函数
* @param workerId 工作ID (0~31)
* @param datacenterId 数据中心ID (0~31)
*/
public SnowflakeIdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}

// ==============================Methods==========================================
/**
* 获得下一个ID (该方法是线程安全的)
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();

//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}

//如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
}
//时间戳改变,毫秒内序列重置
else {
sequence = 0L;
}

//上次生成ID的时间截
lastTimestamp = timestamp;

//移位并通过或运算拼到一起组成64位的ID
return ((timestamp - twepoch) << timestampLeftShift) //
| (datacenterId << datacenterIdShift) //
| (workerId << workerIdShift) //
| sequence;
}

/**
* 阻塞到下一个毫秒,直到获得新的时间戳
* @param lastTimestamp 上次生成ID的时间截
* @return 当前时间戳
*/
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}

/**
* 返回以毫秒为单位的当前时间
* @return 当前时间(毫秒)
*/
protected long timeGen() {
return System.currentTimeMillis();
}

//==============================Test=============================================
/** 测试 */
public static void main(String[] args) {
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
for (int i = 0; i < 1000; i++) {
long id = idWorker.nextId();
System.out.
ce84
println(Long.toBinaryString(id));
System.out.println(id);
}
}

public static SnowflakeIdWorker getInstance(){
return SnowflakeIdWorker;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐