您的位置:首页 > 数据库 > Mongodb

定时任务知多少(二)——持久化quartz到Mongodb中

2015-09-30 23:09 716 查看
上文中,我们粗劣的介绍定时任务相关的知识。并且,我们初步了解了 Spring+quartz 的初步应用:将quartz放在内存中。
通过上文的分析,我们很容易看清:该种方式实现定时任务,较为简单,实现的功能也较为粗劣。由于我们直接把quartz放入内存中,等待执行;我们无法在它执行之前对它进行操作,比如任务暂停、删除等等。

今天,我们就来继续介绍可序列化的quartz的deno。
二、集成Spring,序列化Quartz到Mongodb中

首先,看一下Spring的如下配置:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd" default-lazy-init="true">

<!--配置注解  -->
<context:annotation-config/>
<context:component-scan base-package="com.lzq.quartz" />

<!--quartz调度器  -->
<bean id="scheduler4Stock" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory">
<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
</property>
<property name="configLocation" value="classpath:/spring/quartz_test.properties"></property>
</bean>

</beans>


上面的添加方法中,定时任务管理器会将quartz序列化到Mongodb中。我们需要在下面job的配置quartz_test.properties中,配置Mongodb和Quartz的相关信息:
# Use the MongoDB store
org.quartz.jobStore.class=com.novemberain.quartz.mongodb.MongoDBJobStore
# MongoDB URI (optional if 'org.quartz.jobStore.addresses' is set)
org.quartz.jobStore.mongoUri=mongodb://localhost:27017
# comma separated list of mongodb hosts/replica set seeds (optional if 'org.quartz.jobStore.mongoUri' is set)
# org.quartz.jobStore.addresses=localhost
# database name
org.quartz.jobStore.dbName=test-hello-db
# Will be used to create collections like mycol_jobs, mycol_triggers, mycol_calendars, mycol_locks
org.quartz.jobStore.collectionPrefix=world
# thread count setting is ignored by the MongoDB store but Quartz requries it
org.quartz.threadPool.threadCount=3
org.quartz.jobStore.misfireThreshold = 1800000


上面配置中,我们指定了org.quartz.jobStore.dbName=test-hello-db,这句的意思是我们定义存储quartz的库叫做test-hello-db;指定org.quartz.jobStore.collectionPrefix=world,设置表明的前缀为world(因为会生成多个表,所以要定义前缀,使其相邻且便于辨认)。

job,该类需要继承org.quartz.Job接口,我们可以把它理解成一个任务。这是定时任务到时间时,将要执行的该job类中的execute方法:

import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;

/**
*  库存相关的一个job
* @author lzq
*
*/
public class StockReturnJob implements Job {

private Logger logger = Logger.getLogger(StockReturnJob.class);

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {

JobDataMap jobDataMap = context.getTrigger().getJobDataMap();
Scheduler scheduler = context.getScheduler();

String userId = jobDataMap.getString("userId");
String creditId = jobDataMap.getString("creditId");
int num = jobDataMap.getInt("num");

String orderId = context.getJobDetail().getKey().getName();
String stockId = context.getJobDetail().getKey().getGroup();

// 定时任务开始执行
System.out.println("定时任务开始执行");
System.out.println("jobDataMap中userId="+userId);
System.out.println("jobDataMap中creditId="+creditId);
System.out.println("jobDataMap中num="+num);

// 移除触发器
//		TriggerKey triggerKey = new TriggerKey(orderId, stockId);
//		try {
//			scheduler.unscheduleJob(triggerKey);
//		} catch (SchedulerException e) {
//			e.printStackTrace();
//		}

}

}


下面这个类中,我们定义了定时任务的管理器,在这里,我们添加定时任务、删除定时任务……,同时,我们也可以多定时进行其他操作,如暂定、对触发器进行移出等等操作,本例只提供最基本的介绍,帮助大家快速上手quartz,其他内容,请大家在网络上寻找其他资料。

import java.util.Calendar;

import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.lzq.tool.quartz.schedule.StockReturnJob;

@Component
public class OrderQuartz{

@Autowired
private Scheduler scheduler4Stock;

/**
* 添加一个定时任务
* @param orderId
* @param stockId
*/
public void addQuartz(String orderId,String stockId){

//创建一个job
JobDetailImpl jobDetail = new JobDetailImpl();
jobDetail.setJobClass(StockReturnJob.class);
jobDetail.setKey(new JobKey(orderId, stockId));

//job的数据
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("stockId", stockId);
jobDataMap.put("orderId", orderId);
jobDataMap.put("userId", "user_id_test");
jobDataMap.put("num",1024);

SimpleTriggerImpl strigger = new SimpleTriggerImpl();
strigger.setKey(new TriggerKey(orderId, stockId));

//设置执行时间
Calendar ca = Calendar.getInstance();
ca.add(Calendar.SECOND,45*60);
strigger.setStartTime(ca.getTime());
strigger.setJobDataMap(jobDataMap);
try {
//开始一个定时任务
scheduler4Stock.scheduleJob(jobDetail, strigger);
} catch (SchedulerException e1) {
e1.printStackTrace();
}

}

/**
* 删除一个定时任务
* @param orderId
* @param stockId
* @return true,删除成功;false,删除失败
*/
public boolean deleteQuartz(String orderId,String stockId){
JobKey jk =new JobKey(orderId,stockId);
boolean deleteFlag = false;
try {
deleteFlag = scheduler4Stock.deleteJob(jk);
} catch (SchedulerException e) {
e.printStackTrace();
}
return deleteFlag;
}
}


通过如下程序,运行测试。

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

import com.lzq.tool.quartz.OrderQuartz;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
"classpath:spring/spring.xml"
})
@TransactionConfiguration(transactionManager="transactionManager",defaultRollback=false)
@Transactional
public class QuartzTest{
@Autowired
private OrderQuartz orderQuartz;

@Test
public void testAddOrder() throws Exception {
String orderId ="test-order-lzq1";
String stockId ="test-stock-lzq1";
orderQuartz.addQuartz(orderId, stockId);
}

}


运行结果,会在Mongodb中生成test-hello-db库,且生成的表如下:



生成如上图的四个表,我们会发现,world_locks表总是空的,但是为什么会生成过它呢?从名称上即可做出做好的猜测。加锁,没错。比如多个线程同时添加同一个定时任务(比如,多个用户同时对同一款产品的同一个库存进行操作),如何才能正确条件定时任务呢?其实想到锁,这个问题就很好结局了,大家完全可以把当做乐观锁来处理。

本篇文章介绍的可持久化的定时任务,使用起来比较灵活,用在订单过期、库存失效等业务上非常合适。

实例下载地址:http://download.csdn.net/detail/liu765023051/9240055
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: