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

Quartz+Spring 实现任务监控

2015-06-19 13:18 736 查看
Quartz是一个优秀的任务调度框架,完全基于Java实现,功能强大,易于集成,最近在写了一个小项目,算是对之前接触到的技术做一个总结吧,在这个项目中使用Quartz实现对任务的监控,最终实现的效果如图:



添加效果:



目前已经实现了对Quartz任务的动态添加、暂停、恢复、删除等功能,该项目中使用的是CronTrigger,CronTrigger可以配置灵活的时间规则,是和企业级的应用。

JobDetail界面效果图:



对quartz的研究还在继续,项目也做了不少了,暂时真正研究Quartz应该算刚刚开始,还属于新人阶段,还有一些问题需要解决,在此做一个总结,同时也希望志同道合之人指点一二,互相学习,互相进步吧。

项目简介:

项目名称:cube

项目使用的服务器:tomcat

项目框架:Struts+Spring+Hibernate

数据库:Mysql

开发工具:eclipse

前端:easyui

项目模块如图:



上班族一名,只能趁工作之余来写代码,目前只是实现了系统管理和作业监控部分,系统管理整体使用Shiro实现,目前可以控制到Button级别,作业监控使用Quartz实现

Quartz中 quartz-2.1.7\quartz-2.1.7\docs\dbTables 中有我们实现监控所需的表,依照数据库选择



Quartz数据库核心表如下:

Table NameDescription
QRTZ_CALENDARS存储Quartz的Calendar信息
QRTZ_CRON_TRIGGERS存储CronTrigger,包括Cron表达式和时区信息
QRTZ_FIRED_TRIGGERS存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息
QRTZ_PAUSED_TRIGGER_GRPS存储已暂停的Trigger组的信息
QRTZ_SCHEDULER_STATE存储少量的有关Scheduler的状态信息,和别的Scheduler实例
QRTZ_LOCKS存储程序的悲观锁的信息
QRTZ_JOB_DETAILS存储每一个已配置的Job的详细信息
QRTZ_JOB_LISTENERS存储有关已配置的JobListener的信息
QRTZ_SIMPLE_TRIGGERS存储简单的Trigger,包括重复次数、间隔、以及已触的次数
QRTZ_BLOG_TRIGGERSTrigger作为Blob类型存储
QRTZ_TRIGGER_LISTENERS存储已配置的TriggerListener的信息
QRTZ_TRIGGERS存储已配置的Trigger的信息
下面是Quartz任务监控的具体配置和实现:

Spring配置如下:

<?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:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
<context:annotation-config />
<context:component-scan base-package="com.cube.*" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="cube"></property>
<!-- value 对应persistence.xml中的 persistence-unit name -->
</bean>

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"  />
</bean>

<!-- login action -->

<tx:annotation-driven transaction-manager="txManager" />

</beans>


applicationContext-quartz.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:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
<bean name="quartzScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<property name="configLocation" value="classpath:quartz.properties" />
</bean>

<bean name="jobDetail"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

<property name="jobClass">
<value>com.cube.service.quartz.QuartzJobService</value>
</property>
<property name="durability" value="true" />
</bean>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/cube?useUnicode=true&characterEncoding=UTF8" />
<property name="user" value="root" />
<property name="password" value="" />
<property name="initialPoolSize" value="10" />
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="25" />
<property name="acquireIncrement" value="5" />
<property name="maxIdleTime" value="7200" />
</bean>

</beans>


quartz.properties 配置

org.quartz.scheduler.instanceName = DefaultQuartzScheduler
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 = 60000

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = false
org.quartz.jobStore.maxMisfiresToHandleAtATime=1


任务调度器Service

public interface SchedulerService {

public List<Map<String, Object>> getQrtzTriggers();

/**
* 根据 Quartz Cron Expression 调试任务
*
* @param name Quartz CronTrigger名称
* @param group Quartz CronTrigger组
* @param cronExpression Quartz Cron 表达式,如 "0/10 * * ? * * *"等
*/
void schedule(String name, String group, String cronExpression);

/**
* 根据 Quartz Cron Expression 调试任务
*
* @param name Quartz CronTrigger名称
* @param group Quartz CronTrigger组
* @param cronExpression Quartz CronExpression
*/
void schedule(String name, String group, CronExpression cronExpression);

/**
*
* @param name Quartz CronTrigger名称
* @param group Quartz CronTrigger组
* @param cronExpression Quartz CronExpression
*/
void schedule(String name, String group);

void schedule(Map<String, Object> map);

/**
* 暂停触发器
*
* @param triggerName 触发器名称
*/
void pauseTrigger(String triggerName);

/**
* 暂停触发器
*
* @param triggerName 触发器名称
* @param group 触发器组
*/
void pauseTrigger(String triggerName, String group);

/**
* 恢复触发器
*
* @param triggerName 触发器名称
*/
void resumeTrigger(String triggerName);

/**
* 恢复触发器
*
* @param triggerName 触发器名称
* @param group 触发器组
*/
void resumeTrigger(String triggerName, String group);

/**
* 删除触发器
*
* @param triggerName 触发器名称
* @return
*/
boolean removeTrigdger(String triggerName);

/**
* 删除触发器
*
* @param triggerName 触发器名称
* @param group 触发器组
* @return
*/
boolean removeTrigdger(String triggerName, String group);

}


任务调度器Service实现类

@Transactional
@Service("schedulerService")
public class SchedulerServiceImpl implements SchedulerService {

@Resource(name = "quartzDao")
private QuartzDao quartzDao;

@Autowired
private Scheduler scheduler;
@Autowired
private JobDetail jobDetail;

private static final String NULLSTRING = null;
private static final Date NULLDATE = null;

/**
*
* @param name
* @param group
* @param cronExpression
* @see com.cube.service.SchedulerService#schedule(java.lang.String, java.lang.String,
*      java.lang.String)
*/
public void schedule(String name, String group, String cronExpression) {

try {
schedule(name, group, new CronExpression(cronExpression));

} catch (ParseException e) {
e.printStackTrace();
}

}

/**
* @param name
* @param group
* @param cronExpression
* @see com.cube.service.SchedulerService#schedule(java.lang.String, java.lang.String,
*      org.quartz.CronExpression)
*/
public void schedule(String name, String group, CronExpression cronExpression) {

if (name == null || name.trim().equals("")) {
name = UUID.randomUUID().toString();
}

CronTriggerImpl trigger = new CronTriggerImpl();
trigger.setCronExpression(cronExpression);

TriggerKey triggerKey = new TriggerKey(name, group);

trigger.setJobName(jobDetail.getKey().getName());
trigger.setKey(triggerKey);

try {
scheduler.addJob(jobDetail, true);
if (scheduler.checkExists(triggerKey)) {
scheduler.rescheduleJob(triggerKey, trigger);
} else {
scheduler.scheduleJob(trigger);
}
} catch (SchedulerException e) {
throw new IllegalArgumentException(e);
}

}

/**
* @param map
* @see com.cube.service.SchedulerService#schedule(java.util.Map)
*/
public void schedule(Map<String, Object> map) {
// TODO Auto-generated method stub

}

/**
* @param triggerName
* @see com.cube.service.SchedulerService#pauseTrigger(java.lang.String)
*/
public void pauseTrigger(String triggerName) {
// TODO Auto-generated method stub

}

/**
* @param triggerName
* @param group
* @see com.cube.service.SchedulerService#pauseTrigger(java.lang.String, java.lang.String)
*/
public void pauseTrigger(String triggerName, String group) {

try {
scheduler.pauseTrigger(new TriggerKey(triggerName, group));
} catch (SchedulerException e) {
e.printStackTrace();
}
}

/**
* @param triggerName
* @see com.cube.service.SchedulerService#resumeTrigger(java.lang.String)
*/
public void resumeTrigger(String triggerName) {
// TODO Auto-generated method stub

}

/**
* @param triggerName
* @param group
* @see com.cube.service.SchedulerService#resumeTrigger(java.lang.String, java.lang.String)
*/
public void resumeTrigger(String triggerName, String group) {

TriggerKey triggerKey = new TriggerKey(triggerName, group);

try {
scheduler.resumeTrigger(triggerKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}

/**
* @param triggerName
* @return
* @see com.cube.service.SchedulerService#removeTrigdger(java.lang.String)
*/
public boolean removeTrigdger(String triggerName) {

return removeTrigdger(triggerName, NULLSTRING);

}

/**
* @param triggerName
* @param group
* @return
* @see com.cube.service.SchedulerService#removeTrigdger(java.lang.String, java.lang.String)
*/
public boolean removeTrigdger(String triggerName, String group) {

TriggerKey triggerKey = new TriggerKey(triggerName, group);
try {
scheduler.pauseTrigger(triggerKey);// 停止触发器
return scheduler.unscheduleJob(triggerKey);// 移除触发器
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}

/**
* @return
* @see com.cube.service.SchedulerService#getQrtzTriggers()
*/
public List<Map<String, Object>> getQrtzTriggers() {
return quartzDao.getQrtzTriggers();
}

/**
* @param name
* @param group
* @see com.cube.service.SchedulerService#schedule(java.lang.String, java.lang.String)
*/
public void schedule(String name, String group) {

schedule(name, group, NULLSTRING);
}

}


QuartzDao实现

@Repository("quartzDao")
public class QuartzDao {

private DataSource dataSource;

@Autowired
public void setDataSource(@Qualifier("dataSource") DataSource dataSource) {
this.dataSource = dataSource;
}

// 查询Trigger
public List<Map<String, Object>> getQrtzTriggers() {
List<Map<String, Object>> results = getJdbcTemplate().queryForList(
"select * from QRTZ_TRIGGERS order by start_time");
long val = 0;
String temp = null;
for (Map<String, Object> map : results) {
temp = MapUtils.getString(map, "trigger_name");
if (StringUtils.indexOf(temp, "&") != -1) {
map.put("display_name", StringUtils.substringBefore(temp, "&"));
} else {
map.put("display_name", temp);
}

val = MapUtils.getLongValue(map, "next_fire_time");
if (val > 0) {
map.put("next_fire_time", DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
}

val = MapUtils.getLongValue(map, "prev_fire_time");
if (val > 0) {
map.put("prev_fire_time", DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
}

val = MapUtils.getLongValue(map, "start_time");
if (val > 0) {
map.put("start_time", DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
}

val = MapUtils.getLongValue(map, "end_time");
if (val > 0) {
map.put("end_time", DateFormatUtils.format(val, "yyyy-MM-dd HH:mm:ss"));
}

map.put("trigger_state", Constant.status.get(MapUtils.getString(map, "trigger_state")));
}

return results;
}

private JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(this.dataSource);
}
}


JobClass

public class QuartzJobService extends QuartzJobBean {

// 负责所有任务的调度
private TaskService taskService;

/**
* @param context
* @throws JobExecutionException
* @see org.springframework.scheduling.quartz.QuartzJobBean#executeInternal(org.quartz.JobExecutionContext)
*/
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {

String triggerName = context.getTrigger().getKey().getName();

taskService = (TaskService) getApplicationContext(context).getBean("taskService");

taskService.execute(triggerName);

}

private ApplicationContext getApplicationContext(final JobExecutionContext jobexecutioncontext) {
try {
return (ApplicationContext) jobexecutioncontext.getScheduler().getContext()
.get("applicationContextKey");
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}

}


TaskService所有任务的统一调用接口

public interface TaskService {

/**
* @param triggerName
*/
public void execute(String triggerName);
}


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

@Resource(name = "reportService")
private ReportService reportService;

/**
* 根据TriggerName 调用不同的业务逻辑service
*
* @param triggerName
* @see com.cube.service.TaskService#execute(java.lang.String)
*/
public void execute(String triggerName) {

if ("reportTigger".equalsIgnoreCase(triggerName)) {

reportService.createReport();
} else {
System.out.println(triggerName + ":企业业务逻辑");
}

}

}


/**
* 任务调度器
*
*/
@Controller
@Scope("prototype")
public class TriggerAction extends BaseAction<TriggerEntity> {

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

private TriggerEntity triggerEntity = getModel();

private Map jsonMap = new HashMap();

@Resource(name = "schedulerService")
private SchedulerService schedulerService;

/**
* 跳转到tigger 管理界面
*
* @return
*/
public String trigger() {

return "trigger";
}

/**
* 分页查询Trigger
*
* @return
*/
public String list() {

List<Map<String, Object>> list = schedulerService.getQrtzTriggers();

jsonMap.put("rows", list);
jsonMap.put("total", list.size());
return "list";
}

/**
* 添加触发器
*
* @return
*/
public String save() {

// 获取界面以参数
String triggerName = triggerEntity.getTrigger_name();
String cronExpression = triggerEntity.getCron();
String group = triggerEntity.getTrigger_group();

schedulerService.schedule(triggerName, group, cronExpression);

jsonMap.put("flag", true);

return "save";
}

/**
* 暂停
*
* @return
*/
public String pause() {

schedulerService.pauseTrigger(triggerEntity.getTrigger_name(),
triggerEntity.getTrigger_group());

jsonMap.put("flag", true);

return "pause";
}

/**
* Trigger恢复
*
* @return
*/
public String play() {
schedulerService.resumeTrigger(triggerEntity.getTrigger_name(),
triggerEntity.getTrigger_group());

jsonMap.put("flag", true);
return "play";
}

/**
* 删除
*
* @return
*/
public String deleteTrigger() {

schedulerService.removeTrigdger(triggerEntity.getTrigger_name(),
triggerEntity.getTrigger_group());

jsonMap.put("flag", true);

return "deleteTrigger";
}

public Map getJsonMap() {
return jsonMap;
}

public void setJsonMap(Map jsonMap) {
this.jsonMap = jsonMap;
}

}


参考资料:

https://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/

http://tech.meituan.com/mt-crm-quartz.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: