spring+quartz任务动态添加

注意:只适用于quartz1.8版本以下的,1.8版本以上的因为spring需要等等3.2M2版本才能修复
结合spring+quartz开发个后台的WEB管理系统,系统主要包括以下功能:

1、动态添加、修改和删除数据源,并加入到spring管理。
2、动态注册、修改和删除任务(需要实现的具体quartz业务类),并加入到quartz管理。
3、提供上传第三方包的功能。(主要考虑实现的业务类,需要引入其他的jar包)。
4、在线日志查询分析。
。。。

后台系统的应用领域:

1、执行多个数据库之间的数据交换服务。
2、架设系统与银行之间的通讯服务。
。。。

以前没搞过这方面应用,比较头疼,经过google、百度,初步方案实现如下:

1、实现个servlet用于启动quartz调度。


程序如下:

Java代码
 public class DispatchJobServlet extends HttpServlet {  

private static final long serialVersionUID = -3920177706344758439L;
private ApplicationContext ctx;

public DispatchJobServlet() {
super();
// 初始化自定义类加载器,主要用于加载第三方包和服务程序。
ServiceStartup manguage = new ServiceStartup();
manguage.startUp();
}

/**
* 初始化
*/
public void init(ServletConfig config) throws ServletException {
super.init(config);
ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(config.getServletContext());
StartJobService taskStartService = (StartJobService) ctx.getBean("startJobService");
//启用个线程开始任务调度
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(taskStartService);
}





2、到xml文件查询前台添加的任务队列,加入quartz管理并执行。


Java代码
@Service  
public class StartJobService implements Runnable {
/**
* log4j 记录器
*/
private static final Logger log = Logger.getLogger(StartJobService.class);
@Resource
private SchedulerService schedulerService;

public void run() {
try {
while (true) {
List<JobBo> list = DomParser.findAllJobXml("db.service.xml");
Iterator<JobBo> i = list.iterator();
while (i.hasNext()) {
JobBo job = i.next();
// 如果任务队列不存在则注册并运行
if (!ServiceManager.queryExistsJob(job.getName())) {
try {
schedulerService.schedule(job);
ServiceManager.getJobHolder().put(job.getName(),
job);
} catch (Exception e) {
log.error("服务【" + job.getName() + "】启动失败!", e);
throw new SummerException("服务【" + job.getName()
+ "】启动失败!");
}
}
Thread.sleep(3000);
}
}
} catch (SummerException e) {
throw e;
} catch (Exception e) {
log.error("调度任务出现异常!", e);
}
}
}


3、封装SchedulerService实现quartz调度的方法
封装的出来quartz的接口:

Java代码
public interface SchedulerService {  

/**
* 自定义任务对象并启动任务
*
* @param job
* 任务队列业务对象
*/
void schedule(JobBo job);

/**
* 取得所有调度Triggers
*
* @return
*/
List<Map<String, Object>> getQrtzTriggers();

/**
* 根据名称和组别暂停Tigger
*
* @param triggerName
* @param group
*/
void pauseTrigger(String triggerName, String group);

/**
* 恢复Trigger
*
* @param triggerName
* @param group
*/
void resumeTrigger(String triggerName, String group);

/**
* 删除Trigger
*
* @param triggerName
* @param group
*/
boolean removeTrigdger(String triggerName, String group);
}



实现类:

Java代码
public class SchedulerServiceImpl implements SchedulerService {  

private static final Logger log = LoggerFactory
.getLogger(SchedulerServiceImpl.class);

private Scheduler scheduler;

private JobDetail jobDetail;

public void setScheduler(Scheduler scheduler) {
this.scheduler = scheduler;
}

public void setJobDetail(JobDetail jobDetail) {
this.jobDetail = jobDetail;
}

/**
* 自定义任务对象并启动任务
*/
public void schedule(JobBo job) {
// trigger分类
String category = job.getCategory();
try {
if ("cron".equals(category)) {
scheduleCron(job);
} else {
scheduleSimple(job);
}
} catch (Exception e) {
log.error("任务调度过程中出现异常!");
throw new SummerException(e);
}
}

/**
* simple任务触发
*
* @param job
*/
private void scheduleSimple(JobBo job) {
String name = getTriggerName(job.getName());
// 实例化SimpleTrigger
SimpleTrigger simpleTrigger = new SimpleTrigger();

// 这些值的设置也可以从外面传入,这里采用默放值
simpleTrigger.setJobName(jobDetail.getName());
simpleTrigger.setJobGroup(Scheduler.DEFAULT_GROUP);
simpleTrigger.setRepeatInterval(1000L);
// 设置名称
simpleTrigger.setName(name);

// 设置Trigger分组
String group = job.getGroup();
if (StringUtils.isEmpty(group)) {
group = Scheduler.DEFAULT_GROUP;
}
simpleTrigger.setGroup(group);

// 设置开始时间
Timestamp startTime = job.getStartTime();
if (null != startTime) {
simpleTrigger.setStartTime(new Date());
}

// 设置结束时间
Timestamp endTime = job.getEndTime();
if (null != endTime) {
simpleTrigger.setEndTime(endTime);
}

// 设置执行次数
int repeatCount = job.getRepeatCount();
if (repeatCount > 0) {
simpleTrigger.setRepeatCount(repeatCount);
}

// 设置执行时间间隔
long repeatInterval = job.getRepeatInterval();
if (repeatInterval > 0) {
simpleTrigger.setRepeatInterval(repeatInterval * 1000);
}
try {
JobDataMap jobData = new JobDataMap();
jobData.put("name", job.getName());
jobData.put("desc", job.getDesc());
jobDetail.setJobDataMap(jobData);
scheduler.addJob(jobDetail, true);
scheduler.scheduleJob(simpleTrigger);
scheduler.rescheduleJob(simpleTrigger.getName(), simpleTrigger
.getGroup(), simpleTrigger);
} catch (SchedulerException e) {
log.error("任务调度出现异常!");
log.error(LogGenerator.getInstance().generate(e));
throw new SummerException("任务调度出现异常!");
}
}

/**
* cron任务触发
*
* @param job
*/
private void scheduleCron(JobBo job) {
String name = getTriggerName(job.getName());
try {
JobDataMap jobData = new JobDataMap();
jobData.put("name", job.getName());
jobData.put("desc", job.getDesc());
jobDetail.setJobDataMap(jobData);
scheduler.addJob(jobDetail, true);
CronTrigger cronTrigger = new CronTrigger(name, job.getGroup(),
jobDetail.getName(), Scheduler.DEFAULT_GROUP);
cronTrigger.setCronExpression(job.getCronExpression());
scheduler.scheduleJob(cronTrigger);
scheduler.rescheduleJob(cronTrigger.getName(), cronTrigger
.getGroup(), cronTrigger);
} catch (Exception e) {
log.error("执行cron触发器出现异常!", e);
throw new SummerException("执行cron触发器出现异常!");
}
}

public void schedule(String name, Date startTime, Date endTime,
int repeatCount, long repeatInterval, String group) {
if (name == null || name.trim().equals("")) {
name = UUID.randomUUID().toString();
} else {
// 在名称后添加UUID,保证名称的唯一性
name += "&" + UUID.randomUUID().toString();
}
try {
scheduler.addJob(jobDetail, true);
SimpleTrigger SimpleTrigger = new SimpleTrigger(name, group,
jobDetail.getName(), Scheduler.DEFAULT_GROUP, startTime,
endTime, repeatCount, repeatInterval);
scheduler.scheduleJob(SimpleTrigger);
scheduler.rescheduleJob(SimpleTrigger.getName(), SimpleTrigger
.getGroup(), SimpleTrigger);
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}

public void pauseTrigger(String triggerName, String group) {
try {
scheduler.pauseTrigger(triggerName, group);// 停止触发器
} catch (SchedulerException e) {
throw new SummerException(e);
}
}

public void resumeTrigger(String triggerName, String group) {
try {
scheduler.resumeTrigger(triggerName, group);// 重启触发器
} catch (SchedulerException e) {
log.error("重启触发器失败!");
throw new SummerException(e);
}
}

public boolean removeTrigdger(String triggerName, String group) {
try {
scheduler.pauseTrigger(triggerName, group);// 停止触发器
return scheduler.unscheduleJob(triggerName, group);// 移除触发器
} catch (SchedulerException e) {
throw new SummerException(e);
}
}

private Timestamp parseDate(String time) {
try {
return Timestamp.valueOf(time);
} catch (Exception e) {
log.error("日期格式错误{},正确格式为:yyyy-MM-dd HH:mm:ss", time);
throw new SummerException(e);
}
}

public List<Map<String, Object>> getQrtzTriggers() {
// TODO Auto-generated method stub
return null;
}

/**
* 获取trigger名称
*
* @param name
* @return
*/
private String getTriggerName(String name) {
if (StringUtils.isBlank(StringUtils.trim(name))) {
name = UUID.randomUUID().toString();
} else {
name = name.substring(name.lastIndexOf(".") + 1);
// 在名称后添加UUID,保证名称的唯一性
name += "&" + UUID.randomUUID().toString();
}
return StringUtils.trim(name);
}
}



4、覆盖QuartzJobBean的executeInternal方法,根据“name”名实现任务的动态分配
Java代码
public class EnhanceQuartzJobBean extends QuartzJobBean {  
/**
* log4j 记录器
*/
private static final Logger log = Logger
.getLogger(EnhanceQuartzJobBean.class);

@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
try {
JobDetail t = context.getJobDetail();
JobDataMap map = t.getJobDataMap();
String name = map.getString("name");
String desc = map.getString("desc");
ServiceStartupManguage manguage = new ServiceStartupManguage();
manguage.runService(name, desc);
} catch (Exception e) {
log.error("执行任务出现异常", e);
}
}

public class ServiceStartup {
/**
* log4j 记录器
*/
private static final Logger log = Logger
.getLogger(ServiceStartupManguage.class);

public void startUp() {
// 启动动态重新加载类的服务
StringBuilder sb = new StringBuilder(1024);
sb.append(ServiceManager.getHome() + "work");
String jarPath = ServiceManager.getHome() + "ext";
// 遍历ext文件夹,寻找jar文件
File dir = new File(jarPath);
String[] subFiles = dir.list();
for (int i = 0; i < subFiles.length; i++) {
File file = new File(jarPath + System.getProperty("file.separator")
+ subFiles[i]);
if (file.isFile() && subFiles[i].endsWith("jar")) {
sb.append(File.pathSeparator + jarPath
+ System.getProperty("file.separator") + subFiles[i]);
}
}
ServiceManager.checker = new ClassModifyChecker(ServiceManager.getHome());
ServiceManager.loader = new ServiceClassLoad(DispatchJobServlet.class
.getClassLoader(), (String) sb.toString(), ServiceManager.checker);
ServiceManager.classPath = sb.toString();
}

/**
* 启动后台服务
*
* @author 任鹤峰 2009-02-03
* @param name
* @param desc
* @throws ClassNotFoundException
* @throws NoSuchMethodException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
@SuppressWarnings("unchecked")
public void runService(String name, String desc)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
try {
Object service;
Class cls = null;
if (null != ServiceManager.loader) {
cls = ServiceManager.getLoader().loadClass(name);
} else {
cls = Class.forName(name);
}
Class[] par = null;
Object[] obj = null;
par = new Class[2];
par[0] = String.class;
par[1] = String.class;
obj = new Object[2];
obj[0] = name;
obj[1] = desc;
Constructor ct = cls.getConstructor(par);
service = ct.newInstance(obj);
Method meth = cls.getMethod("start");
meth.invoke(service);
cls = null;
} catch (Exception e) {
log.error("运行注册服务【" + name + "】出现异常", e);
}
}
}

}



5、quartz的配置文件:

Java代码
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="schedulerFactory" singleton="false"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<property name="configLocation" value="classpath:quartz.properties" />
</bean>

<bean id="jobDetail" singleton="false"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>
com.xeranx.summer.scheduling.EnhanceQuartzJobBean
</value>
</property>
</bean>
<bean id="schedulerService" singleton="false"
class="com.xeranx.summer.scheduling.service.SchedulerServiceImpl">
<property name="jobDetail">
<ref bean="jobDetail" />
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
</bean>
</beans>



以上是实现的主要代码: 目前可以实现任务的动态添加并执行,现在的问题是添加多个任务时,最后面的任务会覆盖之前所有的任务。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值