上一篇说过怎么在项目中部署quartz,这节主要说说怎么动态获取数据库的任务进行调度。
关于怎么吧任务存进数据库,取出这都是基本的增删。本篇忽略。
在说今天内容前 先说一个注解@PostConstruct这个是在servlet启动时,就执行的注解。为什么要说他呢?我们项目很多任务是配置在数据库的,所以我们启动项目的时候就要直接执行这些任务。所以要这个注解。
直接上代码
public class SysJob {
private Long jobId; //主键
private String jobName; //任务名称
private String jobGroup; //任务分组
private String jobBeanName; //任务类型
private String cronExpr; //CRON表达式
private String inParam; //任务参数
private int currState; //当前状态 当前状态(0未启动1已启动)
private int isAutoStart; //是否随工程启动 (0不随工程启动1随工程启动)
private String ipAddr; //服务器IP地址
private int isDel; //是否删除 (0未删除1已删除)
private String jobMemo; //备注
private long staffId; //创建人
private String staffName; //创建人
private String createTime; //创建时间
public String getStaffName() {
return staffName;
}
public void setStaffName(String staffName) {
this.staffName = staffName;
}
private String lastModTime; //最后修改时间
public Long getJobId() {
return jobId;
}
public void setJobId(Long jobId) {
this.jobId = jobId;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getJobBeanName() {
return jobBeanName;
}
public void setJobBeanName(String jobBeanName) {
this.jobBeanName = jobBeanName;
}
public String getCronExpr() {
return cronExpr;
}
public void setCronExpr(String cronExpr) {
this.cronExpr = cronExpr;
}
public int getCurrState() {
return currState;
}
public void setCurrState(int currState) {
this.currState = currState;
}
public int getIsAutoStart() {
return isAutoStart;
}
public void setIsAutoStart(int isAutoStart) {
this.isAutoStart = isAutoStart;
}
public int getIsDel() {
return isDel;
}
public void setIsDel(int isDel) {
this.isDel = isDel;
}
public String getJobMemo() {
return jobMemo;
}
public void setJobMemo(String jobMemo) {
this.jobMemo = jobMemo;
}
public long getStaffId() {
return staffId;
}
public void setStaffId(long staffId) {
this.staffId = staffId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getLastModTime() {
return lastModTime;
}
public void setLastModTime(String lastModTime) {
this.lastModTime = lastModTime;
}
public String getIpAddr() {
return ipAddr;
}
public void setIpAddr(String ipAddr) {
this.ipAddr = ipAddr;
}
public String getInParam() {
return inParam;
}
public void setInParam(String inParam) {
this.inParam = inParam;
}
public String getJobGroup() {
return jobGroup;
}
public void setJobGroup(String jobGroup) {
this.jobGroup = jobGroup;
}
}
/**
* servlet上下文
* 是为了把我们调度工厂放进去
*/
private ServletContext servletContext;
/**
* 实现ServletContextAware接口的方法,注入ServletContext,本类实现这个接口
* @param servletContext
*/
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext =servletContext;
}
/**
* bean初始化好之后执行(初始化需要随工程启动而启动的定时任务)
*/
@PostConstruct
public void init() {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = null;
//本机所有ip地址(多网卡,ip用逗号分割)本机只能启动本机设置的job
String ips = getAllLocalHostIP();
try {
//设置全局的scheduler
scheduler = schedulerFactory.getScheduler();
servletContext.setAttribute("scheduler", scheduler);
//启动需要随工程启动而启动的定时任务列表
List jobList = sysJobService.getAutoStartJob();
if(null!=jobList) {
for(SysJob sysJob: jobList) {
//比对配置的ip是否在本机ip串中,是的话,在本机启动此任务
if(ips.indexOf(sysJob.getIpAddr()) != -1) {
startTask(sysJob);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 返回ip地址(如果是多网卡,ip地址用逗号分割)
* @return
*/
public String getAllLocalHostIP() {
StringBuilder sb = new StringBuilder("");
try {
String hostName = getLocalHostName();
if (hostName.length() > 0) {
InetAddress[] addrs = InetAddress.getAllByName(hostName);
if (addrs.length > 0) {
for (int i = 0; i < addrs.length; i++) {
sb.append(addrs[i].getHostAddress());
sb.append(",");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* 启动任务
* @param sysJob 定时任务对象
* @return
*/
public Map startTask(SysJob sysJob) {
LOG.info("在IP:"+sysJob.getIpAddr()+":启动任务:"+sysJob.getJobName());
Scheduler scheduler = (Scheduler) servletContext.getAttribute("scheduler");
Map map = new HashMap();
Boolean flag = null;
String failCause = "";
String jobName = sysJob.getJobId() + "_timer_job";
String groupName = sysJob.getJobGroup();
String triggerName = sysJob.getJobId() + "_timer_trigger";
JobDetail job = JobBuilder.newJob(TimerJob.class).withIdentity(jobName, groupName).build();
job.getJobDataMap().put("sysJob", sysJob);
CronTrigger trigger = null;
try {
//利用框架自身的异常验证cron表达式
trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, groupName)
.withSchedule(CronScheduleBuilder.cronSchedule(sysJob.getCronExpr())).build();
} catch (Exception e) {
e.printStackTrace();
map.put("flag", false);
map.put("failCause", "非法的cron表达式!");
return map;
}
try {
if(scheduler.checkExists(JobKey.jobKey(jobName, groupName))) {
map.put("flag", false);
map.put("failCause", "已经被启动!");
//防止数据库中任务状态与内存中不一致
sysJobService.updateCurrentState(sysJob.getJobId(), 1);
return map;
}
scheduler.scheduleJob(job, trigger);
scheduler.start();
flag = true;
//0表示定时任务的当前状态为停止,1表示定时任务的当前状态是运行
sysJobService.updateCurrentState(sysJob.getJobId(), 1);
} catch (Exception e) {
e.printStackTrace();
flag = false;
failCause = "未知异常,启动失败!";
}
map.put("flag", flag);
map.put("failCause", failCause);
return map;
}
/**
* 停止任务
* @param sysJob 定时任务对象
* @return
*/
public Map<String, Object> stopTask(SysJob sysJob) {
LOG.info("在IP:"+sysJob.getIpAddr()+":停止任务:"+sysJob.getJobName());
Scheduler scheduler = (Scheduler) servletContext.getAttribute("scheduler");
Map<String, Object> map = new HashMap<String, Object>();
Boolean flag = null;
String failCause = "";
String jobName = sysJob.getJobId() + "_timer_job";
String groupName = sysJob.getJobGroup();
String triggerName = sysJob.getJobId() + "_timer_trigger";
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,groupName);
JobKey jobKey = JobKey.jobKey(jobName, groupName);
try {
if(!scheduler.checkExists(jobKey)) {
map.put("flag", false);
map.put("failCause", "已经被关闭!");
//防止数据库中任务状态与内存中不一致
sysJobService.updateCurrentState(sysJob.getJobId(), 0);
return map;
}
scheduler.pauseTrigger(triggerKey);// 停止触发器
scheduler.unscheduleJob(triggerKey);// 移除触发器
scheduler.deleteJob(jobKey);// 删除任务
flag = true;
//0表示定时任务的当前状态为停止,1表示定时任务的当前状态是运行
sysJobService.updateCurrentState(sysJob.getJobId(), 0);
} catch (Exception e) {
e.printStackTrace();
flag = false;
failCause = "未知异常,关闭失败!";
}
map.put("flag", flag);
map.put("failCause", failCause);
return map;
}