Spring4+Quartz2集群下动态创建编辑Job

字数 1265阅读 178

quartz实现原理与集群原理自行百度,本文提供quartz2.2.1版本集群环境动态创建、调度、暂停、恢复、删除Job方法。

1.quartz集群依赖数据库脚本

quartz集群依赖数据库脚本

2.quartz简单监控表


quartz监控表

3.监控列表与新建页面示例


监控列表


Job新建页面

4.quartz.properties示例

org.quartz.scheduler.instanceName = THScheduler 

org.quartz.scheduler.instanceId = AUTO 

 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.JobStoreTXorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate 

org.quartz.jobStore.tablePrefix = QRTZ_ 

org.quartz.jobStore.maxMisfiresToHandleAtATime=10 

org.quartz.jobStore.isClustered = true 

 org.quartz.jobStore.clusterCheckinInterval = 20000

5.容器中基本配置 Spring-quartz.xml示例

<bean name="THScheduler " lazy-init="true" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 

         <property name="dataSource"> <ref bean="dataSource" /> </property>

         <property name="applicationContextSchedulerContextKey" value="applicationContext" />

         <property name="configLocation" value="classpath:quartz.properties" /> 

         <!-- overwriteExistingJobs:覆盖任务调度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情况 --> 

         <property name="overwriteExistingJobs" value="true" /> 

</bean>

6.quartz管理类示例

/**

* 修改任务Cron

*/

public void modifyTigger(String name, String group, String cron)throws SchedulerException {

        Scheduler scheduler = SPRING_CONTEXT.getBean(Scheduler.class);

        TriggerKey key = TriggerKey.triggerKey(name, group);

        Trigger.TriggerState triggerState = scheduler.getTriggerState(key);

        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(key).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();

        scheduler.rescheduleJob(key, trigger);

        JobKey k =new JobKey(name, group);

        log.info("修改任务:{}", name);

        if(!JobDetails.NORMAL.equals(triggerState.name())){

                scheduler.pauseJob(k);

        }

}

/**

* 添加Job

* @param jobName job名称

* @param cls    job执行类

* @param group  群组名称

* @param cron    cron表达式

*/

public void addJob(String jobName, Class cls, String group, String cron)throws SchedulerException {

        Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);

        // 用于描叙Job实现类及其他的一些静态信息,构建一个作业实例

        JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, group).build();

        // 构建一个触发器,规定触发的规则

        Trigger trigger = TriggerBuilder.newTrigger()// 创建一个新的TriggerBuilder来规范一个触发器

            .withIdentity(jobName, group)// 给触发器起一个名字和组名

            .startNow()// 立即执行

            .withSchedule(CronScheduleBuilder.cronSchedule(cron))// 触发器的执行时间

            .build();// 产生触发器

        // 调度Job

        sched.scheduleJob(jobDetail, trigger);

        log.debug("添加任务:{},{},{}", jobName, cls, cron);

        if (!sched.isShutdown()) {

                sched.start();

        }

}

/**

* 暂停一个任务

*/

public void pauseJob(String jobName, String jobGroupName)throws Exception {

        JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);

        Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);

        sched.pauseJob(jobKey);

        log.info("暂停任务:{}", jobName);

}

/**

* 恢复一个任务

*/

public void resumeJob(String jobName, String jobGroupName)throws Exception {

        JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);

        Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);

        sched.resumeJob(jobKey);

        log.info("恢复任务:{}", jobName);

}

/**

* 移除一个任务

*/

public void removeJob(String jobName, String group)throws SchedulerException {

        Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);

        JobKey jobKey =new JobKey(jobName, group);

        // 停止触发器

        sched.pauseJob(jobKey);

        sched.unscheduleJob(new TriggerKey(jobName, group));// 移除触发器

        sched.deleteJob(jobKey);// 删除任务

        log.info("移除任务:{}", jobName);

}

/**

* 启动所有定时任务

*/

public void startJobs() {

        try {

                Scheduler sched = SPRING_CONTEXT.getBean(Scheduler.class);

                sched.start();

        }catch (Exception e) {

                throw new RuntimeException(e);

        }

}

7.web层示例(QuartzService中的方法均为对job监控表进行的单表crud操作)

/**

* Job列表

*/

@RequestMapping(path ="/quartz/list")

public Page findList(HttpServletRequest req){

        log.info("查询job列表");

        return SPRING_CONTEXT.getBean(QuartzService.class).findList(getPageSort(req));

}

/**

* 跳转至job新建页面

*/

@RequestMapping(path ="/quartz/to/add/{id}")

public ModelAndView toAdd(@PathVariable Long id, HttpServletRequest req){

        log.info("调整至新建页面,jobId为{}", id);

        ModelAndView m =new ModelAndView();

        if(id != -1){

                m.addObject("job", SPRING_CONTEXT.getBean(QuartzService.class).findById(id));

        }

        m.addObject("id", id);

        m.setViewName("/dth/quartz/edit.jsp");

        return m;

}

/**

* 编辑Job

*/

@RequestMapping(path ="/quartz/save")

public String save(JobDetails jobDetails, HttpServletRequest req)throws Exception {

    return -1 == jobDetails.getId() ? addJob(jobDetails, getSessionUser(req)) : updateJob(jobDetails);

}

/**

* 新建

*/

public String addJob(JobDetails jobDetails, User user)throws BusinessException {

        log.info("新建job,jobId为{}", jobDetails.getId());

        SPRING_CONTEXT.getBean(QuartzService.class).addJob(jobDetails, user);

        return success("ok");

}

/**

* 修改Cron与备注

*/

public String updateJob(JobDetails jobDetails)throws Exception {

        log.info("修改Cron与备注,jobId为{}", jobDetails.getId());

        SPRING_CONTEXT.getBean(QuartzService.class).updateJob(jobDetails);

        SPRING_CONTEXT.getBean(QuartzManagerService.class).modifyTigger(jobDetails.getNames(), jobDetails.getGroups(),         jobDetails.getCron());

        return success("ok");

}

/**

* 开始调度Job

*/

@RequestMapping(path ="/quartz/schedu/{id}")

public String scheduJob(@PathVariable Long id)throws Exception {

        log.info("开始调度Job,jobId为{}", id);

        JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);

        j.setStatus(JobDetails.NORMAL);

        SPRING_CONTEXT.getBean(QuartzService.class).updateJobStatus(j);

        SPRING_CONTEXT.getBean(QuartzManagerService.class).addJob(j.getNames(), Class.forName(j.getClassName()), j.getGroups(),         j.getCron());

        return success("ok");

}

/**

* 恢复执行Job

*/

@RequestMapping(path ="/quartz/start/{id}")

public String startJob(@PathVariable Long id)throws Exception {

        log.info("恢复执行Job,jobId为{}", id);

        JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);

        j.setStatus(JobDetails.NORMAL);

        SPRING_CONTEXT.getBean(QuartzService.class).updateJobStatus(j);

        SPRING_CONTEXT.getBean(QuartzManagerService.class).resumeJob(j.getNames(), j.getGroups());

        return success("ok");

}

/**

* 暂停Job

*/

@RequestMapping(path ="/quartz/stop/{id}")

public String stopJob(@PathVariable Long id)throws Exception {

        log.info("暂停Job,jobId为{}", id);

        JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);

        j.setStatus(JobDetails.PAUSED);

        SPRING_CONTEXT.getBean(QuartzService.class).updateJobStatus(j);

        SPRING_CONTEXT.getBean(QuartzManagerService.class).pauseJob(j.getNames(), j.getGroups());

        return success("ok");

}

/**

* 删除Job

*/

@RequestMapping(path ="/quartz/delete/{id}")

public String deleteJob(@PathVariable Long id)throws Exception {

        log.info("删除Job,jobId为{}", id);

        JobDetails j = SPRING_CONTEXT.getBean(QuartzService.class).findById(id);

        SPRING_CONTEXT.getBean(QuartzManagerService.class).removeJob(j.getNames(), j.getGroups());

        SPRING_CONTEXT.getBean(QuartzService.class).deleteJob(j); 

        return success("ok");

}

8.实时获取内存中job信息

@RequestMapping(path ="/testQuartz/list")

public List list()throws SchedulerException {

        List list =new ArrayList<>();

        Scheduler scheduler = SPRING_CONTEXT.getBean(Scheduler.class);

        for (String groupName : scheduler.getJobGroupNames()) {

                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {

                           JobDetails j =new JobDetails();

                            j.setNames(jobKey.getName());

                            j.setGroups(jobKey.getGroup());

                            j.setStatus(scheduler.getTriggerState(TriggerKey.triggerKey(jobKey.getName(), jobKey.getGroup())).toString());

                            TriggerKey triggerKey =new TriggerKey(jobKey.getName(), jobKey.getGroup());

                            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

                            j.setCron(trigger.getCronExpression());

                            j.setPreDate(trigger.getPreviousFireTime());

                            j.setNextDate(trigger.getNextFireTime());

                            JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobKey.getName(), jobKey.getGroup()));

                            Class objJobClass = jobDetail.getJobClass();

                            j.setClassName(objJobClass.getName());

                            j.setMethodName(objJobClass.getMethods()[0].getName());

                            list.add(j);

                    }

        }

        return list;

}

9.多个节点时间必须同步