`
wangshiyang
  • 浏览: 66411 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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>  



以上是实现的主要代码: 目前可以实现任务的动态添加并执行,现在的问题是添加多个任务时,最后面的任务会覆盖之前所有的任务。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics