项目ITP(六) spring4.0 整合 Quartz 实现动态任务调度
前言
系列文章:[传送门]
项目需求:
http://www.cnblogs.com/Alandre/p/3733249.html
上一博客写的是基本调度,后来这只能用于,像每天定个时间 进行数据库备份。但是,远远不能在上次的需求上实现。所以需要实现spring4.0 整合 Quartz 实现动态任务调度。
正文
spring4.0 整合 Quartz 实现任务调度。这真是期末项目的最后一篇,剩下到暑假吧。
Quartz 介绍
回顾
上次我们配置了
<!--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实现类
在这里我把它看作工厂类:
package test; import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException; @DisallowConcurrentExecution
public class QuartzJobFactoryImpl implements Job
{ @Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
System.out.println("任务成功运行");
ScheduleJob scheduleJob = (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob");
System.out.println("任务名称 = [" + 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
项目ITP(六) spring4.0 整合 Quartz 实现动态任务调度的更多相关文章
- 项目ITP(五) spring4.0 整合 Quartz 实现任务调度
前言 系列文章:[传送门] 项目需求: 二维码推送到一体机上,给学生签到扫描用.然后需要的是 上课前20分钟 ,幸好在帮带我的学长做 p2p 的时候,接触过.自然 quartz 是首选.所以我就配置了 ...
- SpringBoot2.0整合Quartz实现动态设置定时任务时间
一. 引入依赖 <!-- 引入quartz依赖 --> <dependency> <groupId>org.springframework.boot</ ...
- [CXF REST标准实战系列] 二、Spring4.0 整合 CXF3.0,实现测试接口(转)
转自:[CXF REST标准实战系列] 二.Spring4.0 整合 CXF3.0,实现测试接口 文章Points: 1.介绍RESTful架构风格 2.Spring配置CXF 3.三层初设计,实现W ...
- [CXF REST标准实战系列] 二、Spring4.0 整合 CXF3.0,实现测试接口
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章Points: 1.介绍RESTful架构 ...
- Spring整合Quartz实现动态定时器
一.版本说明 spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错. 原因:spring对于quartz的支持实现,org.springf ...
- Spring整合Quartz实现动态定时器,相关api,定时器添加,删除,修改
一.版本说明 spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错. 原因:spring对于quartz的支持实现,org.springf ...
- spring4.0整合mongodb3.0.4项目实践(用户验证)
我们的项目用到了spring框架和mongdb数据库,随着mongodb升级到3.0已有半年时间,我们也开始随之升级,但是3.0的用户验证有所更改,导致原来的很多配置无法再用. 经过几天的尝试后,终于 ...
- springboot学习入门简易版六---springboot2.0整合全局捕获异常及log4j日志(12-13)
使用Aop实现 1创建异常请求 在原有项目基础上,jspController中创建一个可能发生异常的请求: /** * 全局捕获异常测试 * @param i * @return */ @Reques ...
- Spring4.0整合Hibernate3 .6
转载自:http://greatwqs.iteye.com/blog/1044271 6.5 Spring整合Hibernate 时至今日,可能极少有J2EE应用会直接以JDBC方式进行持久层访问. ...
随机推荐
- CodeForces - 939A,解题报告
题意:给出一个n个点有向图,问是否存在三个点,这三个点构成一个回路.n<=5000 模拟即可. 注意是必须三个点 多了居然不行. import java.util.*; public class ...
- 解决Chrome 70及以上版本的证书问题:Failed to load resource: net::ERR_CERT_SYMANTEC_LEGACY
1.桌面必须要有Chrome 快捷方式 2.进入快捷方式属性 3.修改目标为:"C:\Program Files (x86)\Google\Chrome\Application\chrome ...
- MUI动态生成轮播图片
$$.ajax({ url:'http://localhost:8080/api/v1/food/listFeatureFood', type:'Get', xhrFields: {withCrede ...
- 使用idea搭建maven-web项目
使用idea搭建maven-web项目 1.用idea搭建项目:File--new--project 2.选择jdk版本,选择Maven-archetype-webapp来创建maven-web项目如 ...
- 利用UiWatchers 监听解决安卓自动化各种自动化各种非期待弹窗,弹层,升级,广告,对话框,来电等问题
app自动化时,各种不期待的弹层弹窗,升级广告等时有飞出,由于弹窗具有不定时,不定页面等很多不确定性.有的弹窗很不友好,不×掉,很难进行下一步操作,造成 测试用例失败.而判断是否有弹窗,弹层很麻烦.研 ...
- OC字典的使用
在OC中,字符串.数组.字典是最常见的对象类型,但是在这三个当中,字典的用法相对较少,因为字典的属性和方法比较少,但是一个字典的用法比较复杂,因为在一个字典当中,既可以包含字符串,也可以包含数组,数组 ...
- 判断Array/Object
Object.prototype.isPrototypeOf() / Array.prototype.isPrototypeOf()if(typeof items === "object ...
- Python环境安装及IDE介绍
因为最近时间比较松散,公司的业务也不多,所以想趁机赶紧投入到人工智能的学习大业当中.经过多次比较,看到目前市面上还是使用Python做为基础语言较多,进儿学习算法.人工智能组件.机器学习.数据挖掘等课 ...
- Vue笔记整理——第一天
1.为什么学习Vue? 提高开发效率. 提高效率历程:原生js——>jq(解决兼容性)——>前端模板引擎——>Vue.js(减少DOM操作,注重数据业务逻辑). 2.框架与库的区别? ...
- 阿里,百度面试90%会问的Java面试题
题目一 请对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别? 考点分析: 分析 Exception 和 Error 的区别,是从概念角度考察了 Java 处理机制.总的来 ...