文档章节

项目ITP(六) spring4.0 整合 Quartz 实现动态任务调度

泥沙砖瓦浆木匠
 泥沙砖瓦浆木匠
发布于 2014/05/18 13:46
字数 1468
阅读 9036
收藏 16


2014-05-18 12:51 by Jeff Li

前言

  系列文章:[传送门]

  项目需求:

     http://www.cnblogs.com/Alandre/p/3733249.html

     上一博客写的是基本调度,后来这只能用于,像每天定个时间 进行数据库备份。但是,远远不能在上次的需求上实现。所以需要实现spring4.0 整合 Quartz 实现动态任务调度。

 

正文 

  spring4.0 整合 Quartz 实现任务调度。这真是期末项目的最后一篇,剩下到暑假吧。

    Quartz 介绍

    Quartz is a full-featured, open source job scheduling service that can be integrated with, or used along side virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; 

    Quartz框架是一个全功能、开源的任务调度服务,可以集成几乎任何的java应用程序—从小的单片机系统到大型的电子商务系统。Quartz可以执行上千上万的任务调度。

 

   核心概念

     Quartz核心的概念:scheduler任务调度、Job任务、Trigger触发器、JobDetail任务细节

     相关文档:http://www.quartz-scheduler.org/documentation/quartz-2.2.x/quick-start

回顾

  上次我们配置了

复制代码

<!--Quartz-->
            
    <!-- 集成方式:JobDetailFactoryBean,并且任务类需要继承QuartzJobBean-->
    <!-- 定义jobDetail -->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!-- durability 表示任务完成之后是否依然保留到数据库,默认false   -->
        <property name="durability" value="true" />  
        <!--     目标类  /wmuitp/src/test/SpringQuartz.java-->
        <property name="jobClass" value="test.SpringQuartzTest"></property>
        
           <!--  在这个例子中,jobDataAsMap没有用,此目标类中接受的参数 ,若参数为service,则可以在此进行参数配置,类似struts2 -->
           <!--
        <property name="jobDataAsMap">  
            <map>  
                <entry key="service"><value>simple is the beat</value></entry>  
            </map>  
        </property>            -->
    </bean>
    
    <!-- 定义simpleTrigger触发器 -->
    <!--     
    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="jobDetail"></property>
        <property name="repeatCount">
            <value>8</value>
        </property>
        <property name="repeatInterval">
            <value>1000</value>
        </property>
        <property name="startDelay">
            <value>4</value>
        </property>
    </bean> 
    -->
    
    <!-- 另一种触发器是CornTrigger -->
     <bean id="cornTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
       <property name="jobDetail" ref="jobDetail"/>
       <!-- 每个10秒触发 -->
       <property name="cronExpression" value="0/10 * * * * ?"/>
    </bean> 
    
    <!-- 定义核心调度器 -->
    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
      <property name="triggers">
        <ref bean="cornTrigger"/>
      </property>
    </bean>

复制代码

  #spring实现quartz的方式,先看一下上面配置文件中定义的jobDetail。在Quartz 2.x版本中JobDetail已经是一个接口,Spring是通过将其转换为MethodInvokingJob或StatefulMethodInvokingJob类型来实现的。

 

  这是文档中的源码:

复制代码

/**
 * This implementation applies the passed-in job data map as bean property
 * values, and delegates to <code>executeInternal</code> afterwards.
 * @see #executeInternal */public final void execute(JobExecutionContext context) throws JobExecutionException {    try {        // Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
        Scheduler scheduler = (Scheduler) ReflectionUtils.invokeMethod(getSchedulerMethod, context);
        Map mergedJobDataMap = (Map) ReflectionUtils.invokeMethod(getMergedJobDataMapMethod, context);
 
        BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
        MutablePropertyValues pvs = new MutablePropertyValues();
        pvs.addPropertyValues(scheduler.getContext());
        pvs.addPropertyValues(mergedJobDataMap);
        bw.setPropertyValues(pvs, true);
    }    catch (SchedulerException ex) {        throw new JobExecutionException(ex);
    }
    executeInternal(context);
} 
/**
 * Execute the actual job. The job data map will already have been
 * applied as bean property values by execute. The contract is
 * exactly the same as for the standard Quartz execute method.
 * @see #execute */protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException;

复制代码

 

  MethodInvokingJobDetailFactoryBean中的源码:

复制代码

public void afterPropertiesSet() throws ClassNotFoundException, NoSuchMethodException {
    prepare(); 
    // Use specific name if given, else fall back to bean name.
    String name = (this.name != null ? this.name : this.beanName); 
    // Consider the concurrent flag to choose between stateful and stateless job.
    Class jobClass = (this.concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class); 
    // Build JobDetail instance.
    if (jobDetailImplClass != null) {        // Using Quartz 2.0 JobDetailImpl class...
        this.jobDetail = (JobDetail) BeanUtils.instantiate(jobDetailImplClass);
        BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this.jobDetail);
        bw.setPropertyValue("name", name);
        bw.setPropertyValue("group", this.group);
        bw.setPropertyValue("jobClass", jobClass);
        bw.setPropertyValue("durability", true);
        ((JobDataMap) bw.getPropertyValue("jobDataMap")).put("methodInvoker", this);
    }    else {        // Using Quartz 1.x JobDetail class...
        this.jobDetail = new JobDetail(name, this.group, jobClass);        this.jobDetail.setVolatility(true);        this.jobDetail.setDurability(true);        this.jobDetail.getJobDataMap().put("methodInvoker", this);
    } 
    // Register job listener names.
    if (this.jobListenerNames != null) {        for (String jobListenerName : this.jobListenerNames) {            if (jobDetailImplClass != null) {                throw new IllegalStateException("Non-global JobListeners not supported on Quartz 2 - " +
                        "manually register a Matcher against the Quartz ListenerManager instead");
            }            this.jobDetail.addJobListener(jobListenerName);
        }
    }
 
    postProcessJobDetail(this.jobDetail);
}

复制代码

 

  #既然知道了其所以然,我们就可以真正实战了。

实战 

  听我慢慢道来

减少spring的配置文件

  为了实现一个定时任务,spring的配置代码太多了。动态配置需要们手动来搞。这里我们只需要这要配置即可:

    <!-- quartz配置  动态配置所以我们将 Factory 作为一个service一样的接口 QuartzJobFactory.java-->
    <!-- 调度工厂 -->
    <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    </bean>

 

Job实现类

  在这里我把它看作工厂类:

复制代码

  QuartzJobFactoryImpl   execute(JobExecutionContext context) "任务成功运行"= (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob""任务名称 = [" + scheduleJob.getJobName() + "]"

复制代码

 

任务对应实体类

复制代码

package test;public class ScheduleJob
{     /** 任务id **/
    private String jobId; 
    /** 任务名称 **/
    private String jobName; 
    /** 任务分组 **/
    private String jobGroup; 
    /** 任务状态 0禁用 1启用 2删除**/
    private String jobStatus; 
    /** 任务运行时间表达式 **/
    private String cronExpression; 
    /** 任务描述 **/
    private String desc;    public String getJobId()
    {        return jobId;
    }    public void setJobId(String jobId)
    {        this.jobId = jobId;
    }    public String getJobName()
    {        return jobName;
    }    public void setJobName(String jobName)
    {        this.jobName = jobName;
    }    public String getJobGroup()
    {        return jobGroup;
    }    public void setJobGroup(String jobGroup)
    {        this.jobGroup = jobGroup;
    }    public String getJobStatus()
    {        return jobStatus;
    }    public void setJobStatus(String jobStatus)
    {        this.jobStatus = jobStatus;
    }    public String getCronExpression()
    {        return cronExpression;
    }    public void setCronExpression(String cronExpression)
    {        this.cronExpression = cronExpression;
    }    public String getDesc()
    {        return desc;
    }    public void setDesc(String desc)
    {        this.desc = desc;
    }
    
    
}

复制代码

 

 

下面我们就来测试下:

Controller 测试代码:

复制代码

  @RequestMapping(value = "/quartz")    public ModelAndView quartz() throws SchedulerException 
    {    
        
        //schedulerFactoryBean 由spring创建注入
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");  
        System.out.println(ctx);
        Scheduler scheduler = (Scheduler)ctx.getBean("schedulerFactoryBean");
        
        System.out.println(scheduler);        //这里获取任务信息数据
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();        
        for (int i = 0; i < 3; i++) {
            ScheduleJob job = new ScheduleJob();
            job.setJobId("10001" + i);
            job.setJobName("JobName_" + i);
            job.setJobGroup("dataWork");
            job.setJobStatus("1");
            job.setCronExpression("0/5 * * * * ?");
            job.setDesc("数据导入任务");
            jobList.add(job);
        }        for (ScheduleJob job : jobList) {
         
            TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());         
            //获取trigger,即在spring配置文件中定义的 bean id="myTrigger"
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);            //不存在,创建一个
            if (null == trigger) {
                JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactoryImpl.class)
                    .withIdentity(job.getJobName(), job.getJobGroup()).build();
                jobDetail.getJobDataMap().put("scheduleJob", job);         
                //表达式调度构建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job
                    .getCronExpression());         
                //按新的cronExpression表达式构建一个新的trigger
                trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
                scheduler.scheduleJob(jobDetail, trigger);
            } else {                // Trigger已存在,那么更新相应的定时设置                //表达式调度构建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job
                    .getCronExpression());         
                //按新的cronExpression表达式重新构建trigger
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder).build();         
                //按新的trigger重新设置job执行                scheduler.rescheduleJob(triggerKey, trigger);
            }
        }
        
        ModelAndView mav = new ModelAndView(AdminWebConstant.ADMIN_LOGIN_VIEW);        return mav;
    }

复制代码

 

 #后面这块应该会进一步整理。到时候 会出个更详细的。期待吧

 

测试结果:

总结

  spring quartz

  

感谢及资源共享

    

    http://url.cn/RzETYu 加入我的群

    

    路上走来一步一个脚印,希望大家和我一起。

    感谢读者!很喜欢你们给我的支持。如果支持,点个赞。

    知识来源: 《spring in action》 quartz api


© 著作权归作者所有

共有 人打赏支持
泥沙砖瓦浆木匠

泥沙砖瓦浆木匠

粉丝 799
博文 139
码字总数 170656
作品 4
杭州
程序员
私信 提问
项目ITP(五) spring4.0 整合 Quartz 实现任务调度

2014-05-16 22:51 by Jeff Li 前言   系列文章:[传送门]   项目需求:     二维码推送到一体机上,给学生签到扫描用。然后需要的是 上课前20分钟 ,幸好在帮带我的学长做 p2p 的时候...

泥沙砖瓦浆木匠
2014/05/16
0
0
spring4.0 整合 Quartz 实现任务调度(一)

前言   项目需求:     二维码推送到一体机上,给学生签到扫描用。然后需要的是 上课前20分钟 ,幸好在帮带我的学长做 p2p 的时候,接触过。自然 quartz 是首选。所以我就配置了下,搞...

yzbty23
2016/04/21
119
3
项目ITP(七) javaWeb 整合 Quartz 实现动态调度 并且 持久化

项目ITP(七) javaWeb 整合 Quartz 实现动态调度 并且 持久化 原创地址:http://www.cnblogs.com/Alandre/(泥沙砖瓦浆木匠),需要转载的,保留下! 弟子规 圣人训 首孝弟 次谨信 泛爱众 而亲仁 有...

泥沙砖瓦浆木匠
2014/07/02
0
3
Quartz 2.x与Spring 动态整合

一、Quartz简介 Quartz是一个由James House创立的开源项目,是一个功能强大的作业调度工具,可以计划的执行任务,定时、循环或在某一个时间来执行我们需要做的事,这可以给我们工作上带来很大...

qllinhongyu
2014/07/25
0
0
Spring与Quartz实现定期任务

日志说明: 1、不对Spring的基础环境配置做详细说明; 2、只是记录一下暂时自己从网上及参考手册上查找到的经测试有用的资料 3、记录一下,方便以后自己或需要的朋友使用,后续有新的有用资料...

木子丰
2014/03/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Gradle 提速:每天为你省下一杯喝咖啡的时间

摘要: ### 前言 作为一名 Android 开发同学,当你的工程和代码达到一定规模的时候,相信你一定遇到过编译速度过慢的问题。比如: ![](https://user-gold-cdn.xitu.io/2018/11/6/166e7021c0...

阿里云官方博客
16分钟前
0
0
在 PHPStorm 中如何对远程服务使用 xdebug 进行断点调试

1. 安装 xdebug 1.1. 下载、安装 ➜ ~ wget https://xdebug.org/files/xdebug-2.4.1.tgz➜ ~ tar zxf xdebug-2.4.1.tgz➜ ~ cd xdebug-2.4.1➜ ~ phpize➜ ~ ./configure --with-ph......

whoru
18分钟前
1
0
看完这篇文章还不懂Python装饰器?

1、必备 2.需求来了 初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需调用基础平台提供的功...

糖宝lsh
24分钟前
3
0
Bytom合约预编译

比原项目仓库: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchain/bytom 在开发合约的过程中你们有没有遇到一些问题呢?比如编译合约的过程中不能...

比原链Bytom
26分钟前
2
0
supervisor安装配置

supervisor安装配置 安装 wget -c https://files.pythonhosted.org/packages/44/60/698e54b4a4a9b956b2d709b4b7b676119c833d811d53ee2500f1b5e96dc3/supervisor-3.3.4.tar.gztar -zxvf su......

jackmanwu
51分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部