论坛首页 入门技术论坛

Quartz 在 Spring 中如何动态配置时间

浏览 55827 次
该帖已经被评为新手帖
作者 正文
   发表时间:2009-09-03   最后修改:2009-09-04
spyker 写道
sundoctor 写道
trigger的保存是quartz自己本身实现的,跟jquery没有一点关系,jquery只是前台的ajax调用,当我们调用Scheduler.scheduleJob(Trigger trigger)增加一个Trigger时quartz自己就会往库里插入数据了,对于Trigger数据的增删改都quartz本身持久化支持的,我们不用关心。
添加一个 simple Trigger时往qrtz_simple_triggers写一条记录,同时也会往qrtz_triggers写入一条记录,两个表根据trigger_name、trigger_group对应,开始时间存在qrtz_triggers表中,还有结束时间、上次执行时间、下次执行时间等都存在于qrtz_triggers表中。添加一个 cron Trigger时也一样,同时往qrtz_cron_triggers、qrtz_triggers各写入一条记录。

这个进入数据库的 需要在quartz中做相对应配置
具体的配置 好久不记得了 你可以参考quartz配置文档



具体的配置就是将
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
换成
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
就会自动入库了
0 请登录后投票
   发表时间:2009-09-04  
引用
其实SchedulerService 还可扩展,比如可以注入多个JobDetail,调度不同的JobDetail


请问 这个怎么实现呢?有没有什么思路呢,小弟我刚接触quartz不久,对quartz的结构不是很了解,但同时觉得多个 JobDeatail+动态时间配置 这2个都实现的话 就超级完美了

谢谢
0 请登录后投票
   发表时间:2009-09-04   最后修改:2009-09-04
mxdba321123 写道
引用
其实SchedulerService 还可扩展,比如可以注入多个JobDetail,调度不同的JobDetail


请问 这个怎么实现呢?有没有什么思路呢,小弟我刚接触quartz不久,对quartz的结构不是很了解,但同时觉得多个 JobDeatail+动态时间配置 这2个都实现的话 就超级完美了

谢谢


首先实现多个JobDeatail并注册,比如:
引用

<bean id="jobDetail1" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.sundoctor.example.service.MyQuartzJobBean1</value>
</property>

<bean id="jobDetail2" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.sundoctor.example.service.MyQuartzJobBean2</value>
</property>


<bean id="jobDetail3" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>com.sundoctor.example.service.MyQuartzJobBean3</value>
</property>
...

其次将多个JobDeatail放到一个HashMap中
引用

<util:map id = "jobDeatailMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="org.springframework.scheduling.quartz.JobDetailBean">
<entry key="jobDetail1" ref="jobDetail1"/>
<entry key="jobDetail2" ref="jobDetail2"/>
<entry key="jobDetail3" ref="jobDetail3"/>
</util:map>


然后在SchedulerService 注入jobDeatailMap
@Service("schedulerService")  
public class SchedulerServiceImpl implements SchedulerService {  
   
     private Scheduler scheduler;  
     private Map<String,JobDetailBean> jobDeatailMap;  
   
     @Autowired  
     public void setJobDeatailMap(@Qualifier("jobDeatailMap") Map<String,JobDetailBean> jobDeatailMap) {  
         this.jobDeatailMap = jobDeatailMap;  
     }  
     @Autowired  
     public void setScheduler(@Qualifier("quartzScheduler") Scheduler scheduler) {  
         this.scheduler = scheduler;  
     } 
...


最后,修改SchedulerServiceImpl中的schedule方法,增加以jobDeatailMap KEY名字为参数:
     @Override  
     public void schedule(String jobDetailName,String name, CronExpression cronExpression) {  
         if (name == null || name.trim().equals("")) {  
             name = UUID.randomUUID().toString();  
         }  
   
         //这个时候JobDetail根据jobDetailName从jobDeatailMap获取
         JobDetail jobDetail = jobDeatailMap.get(jobDetailName);
         try {  
             scheduler.addJob(jobDetail, true);  
   
             CronTrigger cronTrigger = new CronTrigger(name, Scheduler.DEFAULT_GROUP, jobDetail.getName(),  
                     Scheduler.DEFAULT_GROUP);  
             cronTrigger.setCronExpression(cronExpression);  
             scheduler.scheduleJob(cronTrigger);  
             scheduler.rescheduleJob(name, Scheduler.DEFAULT_GROUP, cronTrigger);  
         } catch (SchedulerException e) {  
             throw new RuntimeException(e);  
         }  
     }
其它多态方法一样修改,增加jobDetailName参数。    


调用时,传不同的jobDetailName参数就可以调用不用的JobDetail。
SchedulerService schedulerService = (SchedulerService)springContext.getBean("schedulerService"); 

schedulerService.schedule("jobDetail1","审计任务","0/10 * * ? * * *");   

schedulerService.schedule("jobDetail2","发放任务","0/10 * * ? * * *"); 

schedulerService.schedule("jobDetail3","AAA任务","0/10 * * ? * * *"); 
2 请登录后投票
   发表时间:2009-09-04  
恩 开始我是想用list的 后来发现 匹配的问题
改用map后,大体思路和楼主是一样的 现在我只要稍加修改web前端 就可以实现指定任务用自定义的时间设置了,灵活了许多

再次感谢
0 请登录后投票
   发表时间:2009-09-04   最后修改:2009-09-04
其实很多时候只需要一个JobDetail就可以了,也可以达到多个JobDetail一样的效果,一个JobDetail的时候可以在Trigger名称上做扩展,可以在调度任务时给Trigger名称加上不同的前缀或后缀,比如Trigger名称增加一个前缀参数,
     @Override  
     public void schedule(String name, String prefix ,CronExpression cronExpression) {  
         if (name == null || name.trim().equals("")) {  
             name = UUID.randomUUID().toString();  
         }  
   
         try {  
             scheduler.addJob(jobDetail, true);  
             
             //给Trigger名秒加上前缀
             name = prefix + name;

             CronTrigger cronTrigger = new CronTrigger(name, Scheduler.DEFAULT_GROUP, jobDetail.getName(),  
                     Scheduler.DEFAULT_GROUP);  
             cronTrigger.setCronExpression(cronExpression);  
             scheduler.scheduleJob(cronTrigger);  
             scheduler.rescheduleJob(name, Scheduler.DEFAULT_GROUP, cronTrigger);  
         } catch (SchedulerException e) {  
             throw new RuntimeException(e);  
         }  
     }  


然后在QuartzJobBean中的executeInternal方法取到Trigger名秒,然后根据其前缀或后缀调用不同的业务逻辑
 public class MyQuartzJobBean extends QuartzJobBean {  
   
     private SimpleService simpleService;  
       
     public void setSimpleService(SimpleService simpleService) {  
         this.simpleService = simpleService;  
     }  
   
     @Override  
     protected void executeInternal(JobExecutionContext jobexecutioncontext) throws JobExecutionException {  
         Trigger trigger = jobexecutioncontext.getTrigger(); 
         //取得Trigger名称,判断名称前缀或后缀调用不同的业务逻辑
         String triggerName = trigger.getName();  
         if(tirggerName ...){
             simpleService.testMethod(triggerName);  
         }else if(tirggerName ...){
             simpleService.testMethod2(triggerName); 
         }else{
             ...
         }
     }  
   
 }
0 请登录后投票
   发表时间:2009-09-12  
lz问一下:
我要在simpleService里面注入一个继承HibernateDaoSupport的类,在testMethod()方法中执行数据库操作,spring注入为空,我想问一下,是不是因为用了quartz框架的原因,请lz尽快解答,感谢!
0 请登录后投票
   发表时间:2009-09-12  
lz只是需要cronExpression从数据库读取而己,不需要搞的这么复杂.


对于所有spring的${placeholder}值的读取,我扩展了一个JdbcPlaceholderConfigurer用于从数据库读取数据

通过数据库解析spring placeholder的值,配置示例
<bean id="propertyConfigurer" class="cn.org.rapid_framework.spring.beans.factory.config.JdbcPlaceholderConfigurer">
       <property name="dataSource" ref="dataSource"/>
       <property name="sql" value="select config_value,[default_value] from t_app_config where config_key = ?"/>
</bean>



http://www.rapid-framework.org.cn/rapid-javadoc-v2.0.x/cn/org/rapid_framework/spring/beans/factory/config/JdbcPlaceholderConfigurer.html
0 请登录后投票
   发表时间:2009-09-12  
yanyu510 写道
lz问一下:
我要在simpleService里面注入一个继承HibernateDaoSupport的类,在testMethod()方法中执行数据库操作,spring注入为空,我想问一下,是不是因为用了quartz框架的原因,请lz尽快解答,感谢!


在simpleService里面注入一个继承HibernateDaoSupport的类,这个继承HibernateDaoSupport的类也必须实现序列化接口,simpleService类被序列化保存到数据库表 qrtz_job_details的job_class_name字段中,quartz在运行时会读取qrtz_job_details表中的 job_class_name将其反序列化。这也是为什么simpleService和其中注入各属性需要实现Serializable序列化接口的原因,所以你每次修改simpleService类或者其中的继承HibernateDaoSupport的类都要删除 qrtz_job_details表对应的job记录,否则可能会出现空指针异常,因为你如果你没有删除qrtz_job_details表中的记录,你修改的东东并不会自动更新到qrtz_job_details中,你用的还是原来旧版本的simpleService类。

你的这个问题在我另一篇文章《Quartz任务监控管理》有人提到过,你也可以到http://www.iteye.com/topic/441951?page=1看看。

0 请登录后投票
   发表时间:2009-09-12   最后修改:2009-09-12
badqiu 写道
lz只是需要cronExpression从数据库读取而己,不需要搞的这么复杂.


对于所有spring的${placeholder}值的读取,我扩展了一个JdbcPlaceholderConfigurer用于从数据库读取数据

通过数据库解析spring placeholder的值,配置示例
<bean id="propertyConfigurer" class="cn.org.rapid_framework.spring.beans.factory.config.JdbcPlaceholderConfigurer">
       <property name="dataSource" ref="dataSource"/>
       <property name="sql" value="select config_value,[default_value] from t_app_config where config_key = ?"/>
</bean>



http://www.rapid-framework.org.cn/rapid-javadoc-v2.0.x/cn/org/rapid_framework/spring/beans/factory/config/JdbcPlaceholderConfigurer.html


我觉得badqiu对此应用的理解有点偏差,我想要做的并不是简单的从数据库读取cronExpression,而是能够通过前端(比如Web页面)的修改并且不需要重启服务的情况下就可以动态修改配置任务调度时间,并且对于quartx的数据持久化是透明的,只需在数据库增加12张表,修改一下quartx.properties文件的配置,其它并不需要你做些什么额外的斯工作。

JdbcPlaceholderConfigurer继承自PropertyPlaceholderConfigurer
,将原来配置在一个properties文件中的内容转移到数据库而己。JdbcPlaceholderConfigurer只是应用启动时简单的将cronExpression从数据库读取出来,每次修改完数据库后就都需要重启服务,新的修改才会生效。其实JdbcPlaceholderConfigurer还是一种静态配置,只是将原来写在
引用
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="0 0/50 * ? * * *" />
</bean>

中的cronExpression写到另外一个地方:数据库。
0 请登录后投票
   发表时间:2009-09-12  
yanyu510 写道
我还想问一下,我做的数据库备份操作话在testMethod里面,服务器启动的时候时间没到也会调用一次,这样不就乱了吗?这个问题怎么解决?

还有就是我把bakcupDao注入到simpleSerivce里了,我的backupDao里是这么写的:
public boolean backupDateabase(String dbname, String bfname) {
		final String dbName = dbname;
		final String bfname1 = bfname;
		return (Boolean) super.getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						boolean flag = true;
						PreparedStatement pstmt = null;

						try {
							pstmt = session.connection().prepareStatement(
									"{call p_Backup_Or_Restore(?,?,?)}");
							pstmt.setString(1, bfname1);
							pstmt.setString(2, dbName);
							pstmt.setInt(3, 1);
							pstmt.execute();
							System.out.println("数据库已备份");
						} catch (Exception e) {
							flag = false;
							e.printStackTrace();
						}
						return flag;
					}
				});
	}

执行这个方法的,super.getHibernateTemplate()得到的hibernateTemplate为空,是什么原因?
我是初学者,有很多问题不懂,还请LZ多多指导,谢啦!

0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics