- 浏览: 912982 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (537)
- Java SE (114)
- Struts (18)
- Hibernate (25)
- Spring (3)
- Page_Tech (41)
- Others (87)
- Database (29)
- Server (24)
- OpenSource_Tools (15)
- IDE_Tool (22)
- Algorithm (28)
- Interview (22)
- Test (28)
- Hardware (1)
- Mainframe (25)
- Web application (4)
- Linux (3)
- PHP (17)
- Android (1)
- Perl (6)
- ubuntu (1)
- Java EE (9)
- Web Analysis (5)
- Node.js (2)
- javascript (2)
最新评论
-
一键注册:
request.getRequestURL()和request.getRequestURI() -
SuperCustomer:
...
SED的暂存空间和模式空间 -
juyo_ch:
讲得挺好理解的,学习了
java 死锁及解决 -
chinaalex:
最后一题答案正确,但是分析有误.按照如下过程,上一行为瓶,下一 ...
zz智力题 -
liaowuxukong:
多谢博主啦,弱弱的了解了一点。
C++/Java 实现多态的方法(C++)
利用Quartz来实现对任务的调度已经被广泛地应用了,一个利用Quartz来进行任务调度的典型配置如下:
<bean id="testTask" class="com.alisoft.xx.TestTask" /> <bean id="xxJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="concurrent"> <value>false</value> </property> <property name="targetObject"> <ref bean="testTask"/> </property> <property name="targetMethod"> <value>execute</value> </property> </bean> <!-- SimpleTriggerBean可以用org.springframework.scheduling.quartz.CronTriggerBean代替 --> <bean id="xxTriggerBean" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail"> <ref bean="xxJobDetail"/> </property> <property name="startDelay"> <value>1000</value> </property> <property name="repeatInterval"> <value>60000</value> </property> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref local="xxTriggerBean"/> </list> </property> </bean> <bean id="testTask" class="com.alisoft.xx.TestTask" /> <bean id="xxJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="concurrent"> <value>false</value> </property> <property name="targetObject"> <ref bean="testTask"/> </property> <property name="targetMethod"> <value>execute</value> </property> </bean> <!-- SimpleTriggerBean可以用org.springframework.scheduling.quartz.CronTriggerBean代替 --> <bean id="xxTriggerBean" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail"> <ref bean="xxJobDetail"/> </property> <property name="startDelay"> <value>1000</value> </property> <property name="repeatInterval"> <value>60000</value> </property> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref local="xxTriggerBean"/> </list> </property> </bean>
若有多个任务需要调度,则配置多个JobDetail、Trigger即可,待执行的Task bean没有啥任何要求,不需要extends任何class、或者implements任何interface,只是被执行的method需要是无参数的;
但是在我们现实项目中,仅仅完成这样的功能是还不够的,我们还需要争取完成以下几点:
对所有的Task实现执行开始、结束时间的记录;
对每天的Task执行结果持久化、或者通过email、旺旺消息等方式告知相关owner;
当我们有多台Task服务器时,如何保证每个任务只在一台服务器上执行;
针对以上几个问题,我们也都有很简单、直接的办法可以搞定,比如说1、2两点可以直接在每个任务中各自编码完成,但是这样不仅每个task都要写非常类似的重复代码、而且不能保证每个任务的执行情况都被记录,因为某些task的编码人员就不会在意这些非功能性需求;对于第3点,我们也可以通过配置来完成向不同task服务器部署不一样的发布包来完成,但这给发布带来了麻烦,这意味着有多少台task服务器,就需要通过修改配置重新打包并发布多少次;
其实我们可以利用Spring默认提供的AOP来非常优雅的解决这几个问题:扩展MethodInvokingJobDetailFactoryBean来实现对任务调度时的拦截!其关键代码为MethodInvokingJobDetailFactoryBean.MethodInvokingJob.executeInternal(JobExecutionContext context);这个method中;
具体步骤如下:
新增所有Task都需要实现的interface,可参考如下代码:
public interface TaskHandler { /** * 任务调度执行需要实现的method */ TaskResult execute(); } public interface TaskHandler { /** * 任务调度执行需要实现的method */ TaskResult execute(); }
基于MethodInvokingJobDetailFactoryBean实现自定义的JobDetailFactoryBean,在具体执行待调度任务的method前后加入公用逻辑,比如记录开始、结束日期、判断该task是否由该台服务器执行、任务执行完成之后将运行结果进行持久化或者发email等给相关owner;可参考如下代码:
public class AppsMethodInvokingJobDetailFactoryBean extends MethodInvokingJobDetailFactoryBean { protected static final Log logger = LogFactory.getLog(AppsMethodInvokingJobDetailFactoryBean.class); /* (non-Javadoc) * @see org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean#afterPropertiesSet() */ @Override public void afterPropertiesSet() throws ClassNotFoundException, NoSuchMethodException { super.afterPropertiesSet(); logger.info("origin jobClass : " + ((JobDetail)super.getObject()).getJobClass().getName()); // Consider the concurrent flag to choose between stateful and stateless job. if(MethodInvokingJob.class.getName().equals(((JobDetail)super.getObject()).getJobClass().getName())) { ((JobDetail)super.getObject()).setJobClass(AppsMethodInvokingJob.class); } else { ((JobDetail)super.getObject()).setJobClass(AppsStatefulMethodInvokingJob.class); } logger.info("new jobClass : " + ((JobDetail)super.getObject()).getJobClass().getName()); } public static class AppsMethodInvokingJob extends MethodInvokingJob { protected static final Log logger = LogFactory.getLog(AppsMethodInvokingJob.class); private MethodInvoker methodInvoker; private String errorMessage; /** * Set the MethodInvoker to use. */ public void setMethodInvoker(MethodInvoker methodInvoker) { this.methodInvoker = methodInvoker; this.errorMessage = "Could not invoke method '" + this.methodInvoker.getTargetMethod() + "' on target object [" + this.methodInvoker.getTargetObject() + "]"; } /** * Invoke the method via the MethodInvoker. */ protected void executeInternal(JobExecutionContext context) throws JobExecutionException { Date startDate = new Date(); String taskName = methodInvoker.getTargetClass().getName(); TaskResult taskResult; try { if (logger.isInfoEnabled()) { logger.info(taskName + " job start at " + startDate); } //根据当前服务器主机名或者IP判断是否需要执行该任务 //TODO Code //调用具体task执行method代码 taskResult = this.methodInvoker.invoke(); } catch (Exception ex) { logger.error(taskName + " accounted a error : " + this.errorMessage, ex); throw new JobExecutionException(this.errorMessage, ex, false); } finally { if(logger.isInfoEnabled()) { logger.info(taskName + " job end at " + new Date()); } //将task执行结果taskResult进行持久化、或者通知相关owner //TODO Code } } } public static class AppsStatefulMethodInvokingJob extends AppsMethodInvokingJob { } } public class AppsMethodInvokingJobDetailFactoryBean extends MethodInvokingJobDetailFactoryBean { protected static final Log logger = LogFactory.getLog(AppsMethodInvokingJobDetailFactoryBean.class); /* (non-Javadoc) * @see org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean#afterPropertiesSet() */ @Override public void afterPropertiesSet() throws ClassNotFoundException, NoSuchMethodException { super.afterPropertiesSet(); logger.info("origin jobClass : " + ((JobDetail)super.getObject()).getJobClass().getName()); // Consider the concurrent flag to choose between stateful and stateless job. if(MethodInvokingJob.class.getName().equals(((JobDetail)super.getObject()).getJobClass().getName())) { ((JobDetail)super.getObject()).setJobClass(AppsMethodInvokingJob.class); } else { ((JobDetail)super.getObject()).setJobClass(AppsStatefulMethodInvokingJob.class); } logger.info("new jobClass : " + ((JobDetail)super.getObject()).getJobClass().getName()); } public static class AppsMethodInvokingJob extends MethodInvokingJob { protected static final Log logger = LogFactory.getLog(AppsMethodInvokingJob.class); private MethodInvoker methodInvoker; private String errorMessage; /** * Set the MethodInvoker to use. */ public void setMethodInvoker(MethodInvoker methodInvoker) { this.methodInvoker = methodInvoker; this.errorMessage = "Could not invoke method '" + this.methodInvoker.getTargetMethod() + "' on target object [" + this.methodInvoker.getTargetObject() + "]"; } /** * Invoke the method via the MethodInvoker. */ protected void executeInternal(JobExecutionContext context) throws JobExecutionException { Date startDate = new Date(); String taskName = methodInvoker.getTargetClass().getName(); TaskResult taskResult; try { if (logger.isInfoEnabled()) { logger.info(taskName + " job start at " + startDate); } //根据当前服务器主机名或者IP判断是否需要执行该任务 //TODO Code //调用具体task执行method代码 taskResult = this.methodInvoker.invoke(); } catch (Exception ex) { logger.error(taskName + " accounted a error : " + this.errorMessage, ex); throw new JobExecutionException(this.errorMessage, ex, false); } finally { if(logger.isInfoEnabled()) { logger.info(taskName + " job end at " + new Date()); } //将task执行结果taskResult进行持久化、或者通知相关owner //TODO Code } } } public static class AppsStatefulMethodInvokingJob extends AppsMethodInvokingJob { } }
将自定义JobDetailFactoryBean的bean配置设置为abstract,从而减少每个task的相关配置量,新的代码可参考如下配置:
<bean id="appsAbstractJobDetail" class="com.alisoft...AppsMethodInvokingJobDetailFactoryBean" abstract="true"> <property name="concurrent" value="false" /> <property name="targetMethod" value="execute" /> </bean> <bean id="testTaskHandler" class="com.alisoft...task.TestTaskHandler" /> <bean id="testTaskJobDetail" parent="appsAbstractJobDetail"> <property name="targetObject" ref="testTaskHandler" /> </bean> <bean id="testTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="testTaskJobDetail" /> <property name="cronExpression" value="0 10 0 * * ?" /> </bean>
发表评论
-
iPhone5s插件推荐 越狱后必装的50个插件
2014-12-31 16:58 15591. Activator (没有之一的强大手势操作软件)2. ... -
JS automation 环境迁移备注
2014-11-15 11:17 0此次迁移涉及的问题记录如下: 1) Jenkins 直接把 ... -
MacOS 怎么写NFS移动硬盘
2014-11-14 19:13 26971、打开命令行终端。 2、插上移动硬盘,这时候你在Find ... -
How can I resize a partition with Disk Utility (Bottom-up)
2014-10-10 14:30 472Create a new volume in the bla ... -
Outlook 邮件提醒长期显示
2012-08-30 10:38 1348I thought it was one of th ... -
chrome 背景色的设置
2012-07-17 09:56 3019最近换了浏览器,开始喜欢上chrome。 为了保护眼睛 ... -
日常生活中练习右脑
2012-07-12 10:16 1254成年人在日常琐细的生活中,同样可以采取各种方法锻炼右脑。 ... -
大公司面试集锦
2012-06-18 10:23 1364微软十五道面试题 1、有一个整数数组,请求出两两之差绝对值最 ... -
商务英语中的委婉表达
2012-06-18 10:19 12551. 委婉: 1) 动词:think、hope、re ... -
放松颈椎的几个动作
2012-05-29 12:41 1187随时放松颈部肌肉 ... -
drupal简单的体验
2012-05-24 15:41 875第一步: 到 drupal.org下下载最新的Drupal ... -
HtmlParser进行解析原理
2012-05-23 13:48 1167这两天准备做一些网站编程的工作,于是对HtmlParse小研究 ... -
使用HtmlParser提取HTML文本块
2012-05-23 13:46 1460听人介绍说HtmlParser(Java版本)在网页预处理 ... -
[zz] Opencms vs Magnolia
2012-05-22 10:35 2005最近一直在挑选CMS,Opencms和Magnolia是考察的 ... -
面向对象的三个基本特征
2012-04-25 14:56 814面向对象的三个基本特征是:封装、继承、多态。 ... -
Maven vs Ant
2012-04-23 14:35 1191Ant 将提供了很多可以重用的task,例如 copy, mo ... -
zz智力题
2012-03-26 22:50 12631、有两根不均匀分布 ... -
几种开源Portal的简单介绍分析
2012-02-21 22:42 2446主要包括:Pluto,Liferay,eXo,Jetsp ... -
Portal top ten
2012-02-21 22:37 992TOP1 独立网店系统 Sh ... -
英文面试须知
2012-02-16 15:11 978英语面试需要好好准备 ...
相关推荐
class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="shouldRecover" value="false"></property> class="org.springframework.scheduling....
MethodInvokingJobDetailFactoryBean 可以让开发者轻松地配置 JobDetail 对象,并通过 targetObject 和 targetMethod 属性指定要调用的方法。 Spring 提供了多种方式来配置定时任务,可以根据实际情况选择合适的...
本文将深入探讨如何在Spring环境中整合Quartz,主要关注两种方式:JobDetailBean和MethodInvokingJobDetailFactoryBean。这两种方式都能帮助我们在Spring应用中实现定时任务,但它们的使用方法和适用场景略有不同。 ...
例如,`MethodInvokingJobDetailFactoryBean`是用于创建一个基于方法调用的Job实例,它允许你直接指定一个目标对象和执行的方法,这样每次任务执行时就会调用该方法。 集群模式在Quartz中称为“集群(Clustering)...
通过正确配置`MethodInvokingJobDetailFactoryBean`、`CronTriggerBean`以及`SchedulerFactoryBean`,并结合业务接口动态更新Cron表达式,我们可以灵活地控制任务的执行。同时,确保并发控制和任务管理的安全性是...
总结起来,"Spring+Quartz定时集群支持"涉及到的知识点主要包括:Spring与Quartz的集成、Quartz的集群配置、`MethodInvokingJobDetailFactoryBean`的使用、数据库表的设计以及通过IHS等手段实现的任务调度。...
2. **配置 MethodInvokingJobDetailFactoryBean**:接下来,在 Spring 配置文件中使用 `<bean>` 标签定义一个 `MethodInvokingJobDetailFactoryBean` 类型的 bean,并设置相应的属性。这些属性包括: - `target...
在Spring中整合Quartz,我们可以利用Spring的`SchedulerFactoryBean`来创建和管理调度器,同时使用`MethodInvokingJobDetailFactoryBean`和`CronTriggerBean`来定义要执行的任务和触发执行的时间。 首先,我们需要...
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean(); jobDetail.setTargetObject(myTaskService); jobDetail.setTargetMethod("executeTask"); return jobDetail....
在Spring配置中,我们可以使用`MethodInvokingJobDetailFactoryBean`来创建JobDetail,并设置目标对象和方法。 3. **触发器 (Trigger)**:触发器定义了任务何时被执行的规则。比如`CronTrigger`允许我们使用cron...
Spring 提供了 `org.springframework.scheduling.quartz` 包,包含了与 Quartz 集成所需的各种组件,如 `SchedulerFactoryBean`、`MethodInvokingJobDetailFactoryBean` 和 `CronTriggerFactoryBean`。 例如,我们...
在Spring中使用Quartz,首先需要配置`MethodInvokingJobDetailFactoryBean`,它定义了定时任务的具体行为,即哪个对象的哪个方法需要被调用。例如: ```xml ...
这部分定义了一个任务详情bean,名为"jobtask",它使用`MethodInvokingJobDetailFactoryBean`来调用`quartzJob`bean的`work`方法。这意味着当定时任务触发时,`Task`类的`work`方法会被执行。 接下来是触发器的配置...
【SSM集成Quartz1】是指在Spring、Struts2和...接着,使用`MethodInvokingJobDetailFactoryBean`来指定任务执行的具体方法,如`doTask()`,并设置是否允许并发执行。 对于`jobPasswordExpired`,配置如下: ```xml ...
<bean id="schedulerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> ``` 这里`simpleJobTest()`是待执行的方法,`concurrent`属性设置为`false`表示...
- **适用于MethodInvokingJobDetailFactoryBean**: 由于该类型通常需要存储非字符串类型的复杂对象,因此应将其设置为`false`,同时需要处理好对象的序列化和反序列化过程。 **扩展解释**: - 当使用`...
根据提供的部分代码片段,我们可以看到Spring配置文件中定义了一个名为`safe`的任务对象,并通过Quartz的`MethodInvokingJobDetailFactoryBean`创建了一个JobDetail。接下来定义了一个CronTrigger,设置了cron表达式...
2. **`MethodInvokingJobDetailFactoryBean`**:该类用于创建Quartz JobDetail实例,它定义了要执行的方法及其所在对象。 3. **`CronTriggerBean`**与**`SimpleTriggerBean`**:这两个类分别用于基于Cron表达式和...
Spring通过`JobDetailBean`和`MethodInvokingJobDetailFactoryBean`等类进一步简化了Quartz的使用。 `JobDetailBean`是Spring提供的一个用于配置Quartz Job的类。在XML配置中,你可以指定`jobClass`,这是你的...