开发者社区> 问答> 正文

如何通过Spring hibernate quartz动态配置时间查询数据库表信息?

quartz将任务时间持久化到数据库中,定时通过hibernate配置文件查询数据库中相应表的数据,因为有很多任务,cron如果写在配置中会很乱。

展开
收起
小旋风柴进 2016-03-05 08:50:28 3395 0
1 条回答
写回答
取消 提交回答
    1. 实现步骤:
      在页面上设置时间;

    将时间转换为Unix Cron Expression;
    将转换后的时间规则表达式记录到数据库中(也可以写入xml文件中,这里是项目需要记录入数据库中);
    从数据库中得到相应的时间规则表达式;
    更新您的任务触发器的时间设置;
    RESCHEDULE THE JOB。; - )

    1. 具体实现细节:

    1) 在页面上设置时间
    根据具体的业务需求,设置时间规则,下面以某一项目为例,需要 按每月、每周、自定义分为三种规则。
    1 < tr >
    2 < th > 执行这个任务 th >
    3 < td style ="font-weight:bold;" >
    4 < html:radio property ="everyWhat" styleClass ="InputBorderNone" value ="monthly" onclick ="changeStatus(this.value)" > 每月 html:radio >
    5 < html:radio property ="everyWhat" styleClass ="InputBorderNone" value ="weekly" onclick ="changeStatus(this.value)" > 每周 html:radio >
    6 < html:radio property ="everyWhat" styleClass ="InputBorderNone" value ="userDefined" onclick ="changeStatus(this.value)" > 自定义 html:radio >
    7 < html:hidden property ="jobName" value ="compare" />
    8 td >
    9 tr >
    10

    每月则需要选择该月的第几个星期的星期几
    1 < tr style ="display:" id ="whichWeek" >
    2 < th > 选择第几个星期 th >
    3 < td style ="font-weight:bold;" >
    4 < html:select property ="week" >
    5 < html:option value ="1" > 一 html:option >
    6 < html:option value ="2" > 二 html:option >
    7 < html:option value ="3" > 三 html:option >
    8 < html:option value ="4" > 四 html:option >
    9 html:select >
    10 < html:select property ="dayOfMonth" >
    11 < html:option value ="1" > 星期日 html:option >
    12 < html:option value ="2" > 星期一 html:option >
    13 < html:option value ="3" > 星期二 html:option >
    14 < html:option value ="4" > 星期三 html:option >
    15 < html:option value ="5" > 星期四 html:option >
    16 < html:option value ="6" > 星期五 html:option >
    17 < html:option value ="7" > 星期六 html:option >
    18 html:select >
    19 td >
    20 tr >
    21

    每周则需要选择星期几
    1 < tr style ="display:none" id ="whichDay" >
    2 < th > 选择星期 th >
    3 < td style ="font-weight:bold;" >
    4 < html:select property ="dayOfWeek" >
    5 < html:option value ="1" > 星期日 html:option >
    6 < html:option value ="2" > 星期一 html:option >
    7 < html:option value ="3" > 星期二 html:option >
    8 < html:option value ="4" > 星期三 html:option >
    9 < html:option value ="5" > 星期四 html:option >
    10 < html:option value ="6" > 星期五 html:option >
    11 < html:option value ="7" > 星期六 html:option >
    12 html:select >
    13 td >
    14 tr >
    15

    自定义则选择具体的日期,如 2007-1-10

    三种规则都需要设定时间点
    1 < tr >
    2 < th > 起始时间 th >
    3 < td style ="font-weight:bold;" >
    4 < html:select property ="timeType" styleId ="type" onchange ="changeStatus2(this.value)" >
    5 < html:option value ="AM" > 上午 html:option >
    6 < html:option value ="PM" > 下午 html:option >
    7 html:select >
    8 < html:select property ="hour" styleId ="amHours" >
    9 < html:option value ="1" > 1 html:option >
    10 < html:option value ="2" > 2 html:option >
    11 < html:option value ="3" > 3 html:option >
    12 < html:option value ="4" > 4 html:option >
    13 < html:option value ="5" > 5 html:option >
    14 < html:option value ="6" > 6 html:option >
    15 < html:option value ="7" > 7 html:option >
    16 < html:option value ="8" > 8 html:option >
    17 < html:option value ="9" > 9 html:option >
    18 < html:option value ="10" > 10 html:option >
    19 < html:option value ="11" > 11 html:option >
    20 < html:option value ="12" > 12 html:option >
    21 html:select >
    22 < html:select property ="hour" styleId ="pmHours" style ="display:none" >
    23 < html:option value ="13" > 13 html:option >
    24 < html:option value ="14" > 14 html:option >
    25 < html:option value ="15" > 15 html:option >
    26 < html:option value ="16" > 16 html:option >
    27 < html:option value ="17" > 17 html:option >
    28 < html:option value ="18" > 18 html:option >
    29 < html:option value ="19" > 19 html:option >
    30 < html:option value ="20" > 20 html:option >
    31 < html:option value ="21" > 21 html:option >
    32 < html:option value ="22" > 22 html:option >
    33 < html:option value ="23" > 23 html:option >
    34 < html:option value ="0" > 0 html:option >
    35 html:select > 点
    36 < html:text property ="minute" name ="minute" style ="width:20px;" value ="0" onchange ="valTime(this.value)" /> 分
    37 < html:text property ="second" name ="second" style ="width:20px;" value ="0" onchange ="valTime(this.value)" /> 秒(0-59之间的整数)
    38 td >
    39 tr >
    40
    我们的设置页面已经做好了,接下来就是将时间转换为Unix Cron Expression。

    2) 将时间转换为Unix Cron Expression

    需要ActionForm将页面表单数据映射到Action中,然后在Action中转换为cron expression:
    1 SchedulerForm schedulerForm = (SchedulerForm) form;
    2 String jobName = schedulerForm.getJobName();
    3 String cronExpression = "" ;
    4 String[] commonNeeds = {schedulerForm.getSecond(), schedulerForm.getMinute(), schedulerForm.getHour()} ;
    5 String[] monthlyNeeds = {schedulerForm.getWeek(), schedulerForm.getDayOfMonth()} ;
    6 String weeklyNeeds = schedulerForm.getDayOfWeek();
    7 String userDefinedNeeds = schedulerForm.getDate();
    8 String everyWhat = schedulerForm.getEveryWhat();
    9 // 得到时间规则
    10 cronExpression = CronExpConversion.getCronExpression(everyWhat, commonNeeds,
    11 monthlyNeeds, weeklyNeeds, userDefinedNeeds);
    12

    我定义了一个 规则类来处理转换规则(写得不是很好 能用就行 嘿嘿)
    1
    2 /**
    3 * 页面设置转为UNIX cron expressions 转换类
    4 * CronExpConversion
    5 */
    6 public class CronExpConversion {
    7
    8 /**
    9 * 页面设置转为UNIX cron expressions 转换算法
    10 * @param everyWhat
    11 * @param commonNeeds 包括 second minute hour
    12 * @param monthlyNeeds 包括 第几个星期 星期几
    13 * @param weeklyNeeds 包括 星期几
    14 * @param userDefinedNeeds 包括具体时间点
    15 * @return cron expression
    16 */
    17 public static String convertDateToCronExp(String everyWhat,
    18 String[] commonNeeds, String[] monthlyNeeds, String weeklyNeeds,
    19 String userDefinedNeeds) {
    20 String cronEx = "" ;
    21 String commons = commonNeeds[ 0 ] + " " + commonNeeds[ 1 ] + " "
    22 + commonNeeds[ 2 ] + " " ;
    23 String dayOfWeek = "" ;
    24 if ( " monthly " .equals(everyWhat)) {
    25 // eg.: 6#3 (day 6 = Friday and "#3" = the 3rd one in the
    26 // month)
    27 dayOfWeek = monthlyNeeds[ 1 ]
    28 + CronExRelated.specialCharacters
    29 .get(CronExRelated._THENTH) + monthlyNeeds[ 0 ];
    30 cronEx = (commons
    31 + CronExRelated.specialCharacters.get(CronExRelated._ANY)
    32 + " "
    33 + CronExRelated.specialCharacters.get(CronExRelated._EVERY)
    34 + " " + dayOfWeek + " " ).trim();
    35 } else if ( " weekly " .equals(everyWhat)) {
    36 dayOfWeek = weeklyNeeds; // 1
    37 cronEx = (commons
    38 + CronExRelated.specialCharacters.get(CronExRelated._ANY)
    39 + " "
    40 + CronExRelated.specialCharacters.get(CronExRelated._EVERY)
    41 + " " + dayOfWeek + " " ).trim();
    42 } else if ( " userDefined " .equals(everyWhat)) {
    43 String dayOfMonth = userDefinedNeeds.split( " - " )[ 2 ];
    44 if (dayOfMonth.startsWith( " 0 " )) {
    45 dayOfMonth = dayOfMonth.replaceFirst( " 0 " , "" );
    46 }
    47 String month = userDefinedNeeds.split( " - " )[ 1 ];
    48 if (month.startsWith( " 0 " )) {
    49 month = month.replaceFirst( " 0 " , "" );
    50 }
    51 String year = userDefinedNeeds.split( " - " )[ 0 ];
    52 // FIXME 暂时不加年份 Quartz报错
    53 /* cronEx = (commons + dayOfMonth + " " + month + " "
    54 + CronExRelated.specialCharacters.get(CronExRelated._ANY)
    55 + " " + year).trim(); */
    56 cronEx = (commons + dayOfMonth + " " + month + " "
    57 + CronExRelated.specialCharacters.get(CronExRelated._ANY)
    58 + " " ).trim();
    59 }
    60 return cronEx;
    61 }
    62 }
    63
    这样就将页面的时间设置转为了Cron Expression。

    3) 记录时间规则

      我将时间规则存入数据库中,目的是为了生成历史日志,也可以存入XML文件中。当然您也可以省略此步,直接将转换后的规则放入相应的Quartz trigger中。
    

    4) 更新任务触发器的时间设置

    到了关键的一步了,也是最简单的一步,一个方法就可以实现了。
    首先,我们需要通过trigger的名称得到一个CronTriggerBean;
    其次,通过trigger的setCronExpression(String cronExp)方法将新的表达式注入;
    最后,RESCHEDULE THE JOB,OK!
    1 /**
    2 * 自定义定时器调度时间
    3 * @param triggerName 触发器名称
    4 * @throws Exception
    5 */
    6 public void updateNotificationInterval(String triggerName, String triggerId)
    7 throws SchedulerException, ParseException {
    8 // 得到trigger
    9 CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger(
    10 triggerName, Scheduler.DEFAULT_GROUP);
    11 // 得到cron expression
    12 String cronExpression = schedulerDAO.getCronExpression(triggerId);
    13 // 设置trigger的时间规则
    14 trigger.setCronExpression(cronExpression);
    15 // 重置job
    16 scheduler.rescheduleJob(triggerName, Scheduler.DEFAULT_GROUP, trigger);
    17 }
    18
    至此,目的达到了,快乐的看着您的任务在您自定义的时间下快乐的执行,您是否也想像'Happy Feet'中那只快乐的企鹅一样,Show段踢踏呢 ; - D

    PS:忘了说我的Quartz任务是怎么配置的了,罪过,罪过。

    < bean id ="compareJob"

        class ="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" > 
         < property  name ="targetObject"  ref ="compareService"   /> 
         < property  name ="targetMethod"  value ="compare"   /> 
         < property  name ="concurrent"  value ="false"   /> 
     </ bean >  
    
     < bean  id ="compareTrigger" 
        class ="org.springframework.scheduling.quartz.CronTriggerBean" > 
         < property  name ="jobDetail"  ref ="compareJob"   /> 
         < property  name ="cronExpression" >              
             < value > 0 39 16 20 * ? </ value > 
         </ property > 
     </ bean > 
    

    < bean id ="schedulerFactory"

        class ="org.springframework.scheduling.quartz.SchedulerFactoryBean" > 
         < property  name ="triggers" > 
             < list >                     
                     < ref  local ="compareTrigger"   /> 
             </ list > 
         </ property > 
     </ bean >
    

    1. 实现步骤:
      在页面上设置时间;

    将时间转换为Unix Cron Expression;
    将转换后的时间规则表达式记录到数据库中(也可以写入xml文件中,这里是项目需要记录入数据库中);
    从数据库中得到相应的时间规则表达式;
    更新您的任务触发器的时间设置;
    RESCHEDULE THE JOB。; - )

    1. 具体实现细节:
      1) 在页面上设置时间

    根据具体的业务需求,设置时间规则,下面以某一项目为例,需要 按每月、每周、自定义分为三种规则。

       < tr > 
                 < th > 执行这个任务 </ th > 
                 < td  style ="font-weight:bold;" > 
                  < html:radio  property ="everyWhat"  styleClass ="InputBorderNone"  value ="monthly"  onclick ="changeStatus(this.value)" > 每月 </ html:radio > 
                  < html:radio  property ="everyWhat"  styleClass ="InputBorderNone"  value ="weekly"  onclick ="changeStatus(this.value)" > 每周 </ html:radio > 
                  < html:radio  property ="everyWhat"  styleClass ="InputBorderNone"  value ="userDefined"  onclick ="changeStatus(this.value)" > 自定义 </ html:radio > 
                  < html:hidden  property ="jobName"  value ="compare"   /> 
                 </ td > 
       </ tr > 

    每月则需要选择该月的第几个星期的星期几

       < tr  style ="display:"  id ="whichWeek" > 
                 < th > 选择第几个星期 </ th > 
                 < td  style ="font-weight:bold;" > 
                  < html:select  property ="week" > 
                   < html:option  value ="1" > 一 </ html:option > 
                   < html:option  value ="2" > 二 </ html:option > 
                   < html:option  value ="3" > 三 </ html:option > 
                   < html:option  value ="4" > 四 </ html:option > 
                  </ html:select > 
                 < html:select  property ="dayOfMonth" > 
                  < html:option  value ="1" > 星期日 </ html:option > 
                  < html:option  value ="2" > 星期一 </ html:option > 
                  < html:option  value ="3" > 星期二 </ html:option > 
                  < html:option  value ="4" > 星期三 </ html:option > 
                  < html:option  value ="5" > 星期四 </ html:option > 
                  < html:option  value ="6" > 星期五 </ html:option > 
                  < html:option  value ="7" > 星期六 </ html:option > 
                 </ html:select > 
               </ td >  
       </ tr > 

    每周则需要选择星期几

      < tr  style ="display:none"  id ="whichDay" > 
                 < th > 选择星期 </ th > 
                 < td  style ="font-weight:bold;" > 
                  < html:select  property ="dayOfWeek" > 
                   < html:option  value ="1" > 星期日 </ html:option > 
                   < html:option  value ="2" > 星期一 </ html:option > 
                   < html:option  value ="3" > 星期二 </ html:option > 
                   < html:option  value ="4" > 星期三 </ html:option > 
                   < html:option  value ="5" > 星期四 </ html:option > 
                  < html:option  value ="6" > 星期五 </ html:option > 
                  < html:option  value ="7" > 星期六 </ html:option > 
                 </ html:select > 
              </ td >  
        </ tr > 

    自定义则选择具体的日期,如 2007-1-10

    三种规则都需要设定时间点

           < tr > 
                < th > 起始时间 </ th > 
                 < td  style ="font-weight:bold;" > 
                  < html:select  property ="timeType"  styleId ="type"  onchange ="changeStatus2(this.value)" > 
                   < html:option  value ="AM" > 上午 </ html:option > 
                   < html:option  value ="PM" > 下午 </ html:option > 
                  </ html:select > 
                  < html:select  property ="hour"  styleId ="amHours" > 
                   < html:option  value ="1" > 1 </ html:option > 
                  < html:option  value ="2" > 2 </ html:option > 
                  < html:option  value ="3" > 3 </ html:option > 
                  < html:option  value ="4" > 4 </ html:option > 
                  < html:option  value ="5" > 5 </ html:option > 
                  < html:option  value ="6" > 6 </ html:option > 
                  < html:option  value ="7" > 7 </ html:option > 
                  < html:option  value ="8" > 8 </ html:option > 
                  < html:option  value ="9" > 9 </ html:option > 
                  < html:option  value ="10" > 10 </ html:option > 
                  < html:option  value ="11" > 11 </ html:option > 
                  < html:option  value ="12" > 12 </ html:option > 
                 </ html:select > 
                 < html:select  property ="hour"  styleId ="pmHours"  style ="display:none" > 
                  < html:option  value ="13" > 13 </ html:option > 
                  < html:option  value ="14" > 14 </ html:option > 
                  < html:option  value ="15" > 15 </ html:option > 
                < html:option  value ="16" > 16 </ html:option > 
                 < html:option  value ="17" > 17 </ html:option > 
                  < html:option  value ="18" > 18 </ html:option > 
                  < html:option  value ="19" > 19 </ html:option > 
                 < html:option  value ="20" > 20 </ html:option > 
                  < html:option  value ="21" > 21 </ html:option > 
                  < html:option  value ="22" > 22 </ html:option > 
                  < html:option  value ="23" > 23 </ html:option > 
                  < html:option  value ="0" > 0 </ html:option > 
                 </ html:select >  点
                  < html:text  property ="minute"  name ="minute"  style ="width:20px;"  value ="0"  onchange ="valTime(this.value)"   />  分
                  < html:text  property ="second"  name ="second"  style ="width:20px;"  value ="0"  onchange ="valTime(this.value)"   />  秒(0-59之间的整数)
            </ td >  
      </ tr > 

    我们的设置页面已经做好了,接下来就是将时间转换为Unix Cron Expression。
    2) 将时间转换为Unix Cron Expression
    需要ActionForm将页面表单数据映射到Action中,然后在Action中转换为cron

    expression: 
       SchedulerForm schedulerForm  =  (SchedulerForm) form;
              String jobName  =  schedulerForm.getJobName();
              String cronExpression  =   "" ;
               String[] commonNeeds  =   {schedulerForm.getSecond(), schedulerForm.getMinute(), schedulerForm.getHour()} ;
               String[] monthlyNeeds  =   {schedulerForm.getWeek(), schedulerForm.getDayOfMonth()} ;
              String weeklyNeeds  =  schedulerForm.getDayOfWeek();
              String userDefinedNeeds  =  schedulerForm.getDate();
              String everyWhat  =  schedulerForm.getEveryWhat();
               // 得到时间规则 
              cronExpression  =  CronExpConversion.getCronExpression(everyWhat, commonNeeds,
                    monthlyNeeds, weeklyNeeds, userDefinedNeeds);

    我定义了一个 规则类来处理转换规则(写得不是很好 能用就行 嘿嘿)

    /** 
    * 页面设置转为UNIX cron expressions 转换类
    * CronExpConversion
     */ 
    public   class  CronExpConversion  {
       
         /** 
        * 页面设置转为UNIX cron expressions 转换算法
       *  @param  everyWhat
       *  @param  commonNeeds 包括 second minute hour
       *  @param  monthlyNeeds 包括 第几个星期 星期几
       *  @param  weeklyNeeds  包括 星期几
       *  @param  userDefinedNeeds  包括具体时间点
       *  @return  cron expression
        */ 
       public   static  String convertDateToCronExp(String everyWhat,
              String[] commonNeeds, String[] monthlyNeeds, String weeklyNeeds,
               String userDefinedNeeds)  {
          String cronEx  =   "" ;
          String commons  =  commonNeeds[ 0 ]  +   "   "   +  commonNeeds[ 1 ]  +   "   " 
                   +  commonNeeds[ 2 ]  +   "   " ;
          String dayOfWeek  =   "" ;
            if  ( " monthly " .equals(everyWhat))  {
               //  eg.: 6#3 (day 6 = Friday and "#3" = the 3rd one in the
               //  month) 
               dayOfWeek  =  monthlyNeeds[ 1 ]
                       +  CronExRelated.specialCharacters
                              .get(CronExRelated._THENTH)  +  monthlyNeeds[ 0 ];
              cronEx  =  (commons
                       +  CronExRelated.specialCharacters.get(CronExRelated._ANY)
                       +   "   " 
                       +  CronExRelated.specialCharacters.get(CronExRelated._EVERY)
                       +   "   "   +  dayOfWeek  +   "   " ).trim();
          }   else   if  ( " weekly " .equals(everyWhat))  {
             dayOfWeek  =  weeklyNeeds;  //  1 
               cronEx  =  (commons
                       +  CronExRelated.specialCharacters.get(CronExRelated._ANY)
                     +   "   " 
                      +  CronExRelated.specialCharacters.get(CronExRelated._EVERY)
                       +   "   "   +  dayOfWeek  +   "   " ).trim();
           }   else   if  ( " userDefined " .equals(everyWhat))  {
              String dayOfMonth  =  userDefinedNeeds.split( " - " )[ 2 ];
               if  (dayOfMonth.startsWith( " 0 " ))  {
                  dayOfMonth  =  dayOfMonth.replaceFirst( " 0 " ,  "" );
              } 
              String month  =  userDefinedNeeds.split( " - " )[ 1 ];
                if  (month.startsWith( " 0 " ))  {
                 month  =  month.replaceFirst( " 0 " ,  "" );
             } 
              String year  =  userDefinedNeeds.split( " - " )[ 0 ];
               // FIXME 暂时不加年份 Quartz报错 
                /* cronEx = (commons + dayOfMonth + " " + month + " "
                      + CronExRelated.specialCharacters.get(CronExRelated._ANY)
                     + " " + year).trim(); */ 
              cronEx  =  (commons  +  dayOfMonth  +   "   "   +  month  +   "   " 
                       +  CronExRelated.specialCharacters.get(CronExRelated._ANY)
                       +   "   " ).trim();
          } 
           return  cronEx;
     }     
     } 

    这样就将页面的时间设置转为了Cron Expression。
    3) 记录时间规则
    我将时间规则存入数据库中,目的是为了生成历史日志,也可以存入XML文件中。当然您也可以省略此步,直接将转换后的规则放入相应的Quartz trigger中。
    4) 更新任务触发器的时间设置
    到了关键的一步了,也是最简单的一步,一个方法就可以实现了。
    首先,我们需要通过trigger的名称得到一个CronTriggerBean;
    其次,通过trigger的setCronExpression(String cronExp)方法将新的表达式注入;
    最后,RESCHEDULE THE JOB,OK!

          /** 
           * 自定义定时器调度时间
           *  @param  triggerName 触发器名称
            *  @throws  Exception 
            */ 
           public   void  updateNotificationInterval(String triggerName, String triggerId)
                   throws  SchedulerException, ParseException  {
              // 得到trigger 
              CronTriggerBean trigger  =  (CronTriggerBean) scheduler.getTrigger(
                     triggerName, Scheduler.DEFAULT_GROUP);
            // 得到cron expression         
             String cronExpression  =  schedulerDAO.getCronExpression(triggerId);
             // 设置trigger的时间规则 
              trigger.setCronExpression(cronExpression);
             // 重置job 
              scheduler.rescheduleJob(triggerName, Scheduler.DEFAULT_GROUP, trigger);
        } 

    至此,目的达到了,快乐的看着您的任务在您自定义的时间下快乐的执行,您是否也想像'Happy Feet'中那只快乐的企鹅一样,Show段踢踏呢 ; - D

    
    PS:忘了说我的Quartz任务是怎么配置的了,罪过,罪过。
    

    < bean id ="compareJob"

        class ="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" > 
         < property  name ="targetObject"  ref ="compareService"   /> 
         < property  name ="targetMethod"  value ="compare"   /> 
         < property  name ="concurrent"  value ="false"   /> 
     </ bean >  
    
     < bean  id ="compareTrigger" 
        class ="org.springframework.scheduling.quartz.CronTriggerBean" > 
         < property  name ="jobDetail"  ref ="compareJob"   /> 
         < property  name ="cronExpression" >              
             < value > 0 39 16 20 * ? </ value > 
         </ property > 
     </ bean > 
    

    < bean id ="schedulerFactory"

        class ="org.springframework.scheduling.quartz.SchedulerFactoryBean" > 
         < property  name ="triggers" > 
             < list >                     
                     < ref  local ="compareTrigger"   /> 
             </ list > 
         </ property > 
     </ bean >
    2019-07-17 18:52:51
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载