您的位置:首页 > 编程语言 > Java开发

java定时框架Quartz的简单应用(附:读取properties文件参数代码)

2017-01-11 18:19 821 查看

1. 实现一个简单的定时任务

1.1 步骤如下:

(1)下载Quartz的压缩包,并解压,其中lib文件夹下的jar包为Quartz需要用到的包,如图1



(2)简单的定时任务,在每分钟输出一次hellojob

//测试版本为quartz1.80,在quartz2.23下会报错
public class QuartzTest1 {
public static void main(String[] args) {
JobDetail jobDetail = new JobDetail("Hello_Job","Hello_Job_Group",HelloJob.class);
JobDataMap dataMap = new JobDataMap();
jobDetail.setJobDataMap(dataMap);
CronTrigger trigger = new CronTrigger("TriggerName","TriggerGroupName" );
try {
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler scheduler = schedFact.getScheduler();
//时间格式:秒 分 时 日 月 年,*为任意
trigger.setCronExpression("0 * * * * ?");
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
//为定时作业调度预留时间
Thread.sleep(600000);
scheduler.shutdown();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//分割线--------------------------------------------
//在quartz2.23的示例
public class QuartzTest1 {
public static void main(String[] args) {
SchedulerFactory sf = new StdSchedulerFactory();
try {
Scheduler sched = sf.getScheduler();
Date nowTime = new Date();
System.out.println(nowTime);
//将分秒数进位取整nowTime=15:40:28 runTime=15:41:00
Date runTime = DateBuilder.evenMinuteDate(nowTime);
System.out.println(runTime);
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
//单次定时任务
//Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();
//多次循环定时任务"0/20 * * * * ?"从*年*月*日  *:*:00秒开始每20秒执行一次
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(CronScheduleBuilder.cronSchedule("0/20 * * * * ?"))
.build();
Date ft = sched.scheduleJob(job, trigger);
System.out.println(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
+ trigger.getCronExpression());
sched.start();
Thread.sleep(60000*5);
sched.shutdown(true);
} catch (Exception e) {
//
}
}
}

//继承Job类的具体定时任务
public class HelloJob implements Job {

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("hello job......start:"+new Date());
}
}


2. Quartz中一些常用的方法(quartz2.23)

2.1 Scheduler类的一些方法

2.11 获取Scheduler对象

SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();


2.12 将JobDetail对象与Trigger对象绑定到Scheduler对象上

Date ft = sched.scheduleJob(JobDetail job,Trigger trigger);
//可绑定多个job及trigger返回的Date为第一次定时任务的开始执行时间


2.13 Scheduler对象的开始与结束

sched.start();
sched.shutdown(true);


2.14 重新执行绑定执行定时任务

sched.rescheduleJob(trigger.getKey(), trigger);


2.15 获取一些统计信息

SchedulerMetaData metaData = sched.getMetaData();
//获得绑定执行的job执行的次数
metaData.getNumberOfJobsExecuted();


2.2 JobDetail类的一些方法

2.21 创建JobDetail对象及设置基本属性

JobDetail job = org.quartz.JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();


2.22 获取JobDetail对象job的的Identity信息

job.getKey();//打印结果为group1.job1(该job对象创建于2.21)


2.23 手动执行JobDetail(不创建Trigger)

JobDetail job = org.quartz.JobBuilder.newJob(SimpleJob.class).withIdentity("job8", "group1").storeDurably().build();
sched.addJob(job, true);
sched.triggerJob(org.quartz.JobKey.jobKey("job8", "group1"));


2.24 通过JobDataMap和实现Job接口的execute()方法传参

JobDetail job1 = newJob(ColorJob.class).withIdentity("job1", "group1").build();
job1.getJobDataMap().put(ColorJob.FAVORITE_COLOR, "Green");
job1.getJobDataMap().put(ColorJob.EXECUTION_COUNT, 1);
//或在创建JobDetail对象时使用.usingJobData("Key","Value").build();

//在Job的实现类的execute(JobExecutionContext context)中,FAVORITE_COLOR为该类的字符串常量
JobDataMap data = context.getJobDetail().getJobDataMap();
String favoriteColor = data.getString(FAVORITE_COLOR);
data.put(EXECUTION_COUNT, ++count);


2.3 Trigger类的一些方法

2.31 创建Trigger对象及设置基本属性

Trigger trigger = org.quartz.TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(Date runTime).build();

SimpleTrigger trigger = (SimpleTrigger) org.quartz.TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(Date startTime).build();

CronTrigger trigger = org.quartz.TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(org.quartz.CronScheduleBuilder.cronSchedule("0/20 * * * * ?"))
.build();


2.32 创建Trigger对象时设置定时信息

//withIntervalInSeconds(10)间隔时间为10秒,withRepeatCount(10)重复次数为10次,共执行11次
SimpleTrigger trigger = org.quartz.TriggerBuilder.newTrigger().withIdentity("trigger3", "group1")
.startAt(Date startTime).withSchedule(org.quartz.SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)).build();

//只执行一次futureDate(5,IntervalUnit.MINUTE)在5分钟之后
startAt(futureDate(5, IntervalUnit.MINUTE))

//时间间隔为40秒(withIntervalInMinutes(5)间隔5分钟)且没有重复执行次数限制
org.quartz.SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(40).repeatForever()


2.33 创建Trigger对象时绑定job

trigger = org.quartz.TriggerBuilder.newTrigger().withIdentity("trigger3","group2").startAt(Date startTime).forJob(JobDetail job).build();
//绑定到Scheduler对象上:sched.scheduleJob(trigger);


2.34 获取Trigger对象的信息的方法

方法说明
trigger.getRepeatCount()获得该trigger的执行次数
trigger.getRepeatInterval()获得该trigger重复间隔时长的毫秒数
trigger.getCronExpression()获取trigger(CronTrigger)设置的时间表达式

2.4 JobExecutionContext类的一些方法

该类通过实现Job接口,复写其
public void execute(JobExecutionContext context) throws JobExecutionException
方法后得到

2.41 获取当前JobDetail的jobKey

JobKey jobKey = context.getJobDetail().getKey();


2.42

2.5 一些时间表达式例子

设置trigger的时间表达式:
CronTrigger trigger = org.quartz.TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(org.quartz.CronScheduleBuilder.cronSchedule("0/20 * * * * ?"))
.build();


时间表达式说明
0/20 * * * * ?每间隔20秒执行一次
15 0/2 * * * ?在每2分钟的第15秒执行
0 0/2 8-17 * * ?只在8am-5pm这段时间每2分钟执行一次
0 0/3 17-23 * * ?只在5pm-11pm这段时间每3分钟执行一次
0 0 10am 1,15 * ?在每个月的1号和15号早上10点执行
0,30 * * ? * MON-FRI在星期一至星期五期间每30秒执行一次
0,30 * * ? * SAT,SUN在星期六至星期日期间每30秒执行一次

3. web项目的定时任务

第一步:在web.xml文件里,设置web项目启动时初始化的Servlet,使项目启动时能够调用实现定时任务业务逻辑的类。

**(1) web.xml中的设置**


<servlet>
<display-name>QuartzTestServlet</display-name>
<servlet-name>QuartzTestServlet</servlet-name>
<servlet-class>package.QuartzTestServlet</servlet-class>
<!-- 当load-on-startup值为负整数或者未指定时,容器在该servlet被调用时加载 -->
<!-- 当其值为0和正整数时,容器启动时加载,值越小,优先级越高 -->
<load-on-startup>2</load-on-startup>
</servlet>
<!-- 可选,根据实际情况选择时候设置servlet-mapping -->
<servlet-mapping>
<servlet-name>QuartzTestServlet</servlet-name>
<url-pattern>/QuartzTestServlet</url-pattern>
</servlet-mapping>


**(2)package.QuartzTestServlet类需要继承javax.servlet.http.HttpServlet类,并复写public void init()方法。该方法中主要是调用具体设置调度定时作业、添加删除定时作业的类,还可以进行是否启动定时任务的判定、日志输出等。**


import org.apache.log4j.Logger;

public class QuartzTestServlet extends HttpServlet{
private static final long serialVersionUID = 5148765487841631133L;
//org.apache.log4j.Logger用于日志输出信息
private static final Logger log=Logger.getLogger(QuartzTestServlet.class);
@Override
public void init(){
log.info("QuartzTestServlet#init() is run..........");
try {
//QuartzTestManager自己写的类用于实现添加定时任务的业务逻辑
QuartzTestManager.getInstance().run();
} catch (SchedulerException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("错误~~~~~~~~~~");
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doPost(req, resp);
}
}


第二步:编写QuartzTestManager实现定时任务调度的业务逻辑。

public class QuartzTestManager {
private static final Logger log=Logger.getLogger(QuartzTest.class);
private static final String JOB_GROUP_NAME = "quartzTestJobs";
private static final String TRIGGER_GROUP_NAME = "quartzTestTriggers";
private static final String POSTFIX_JOB = "_Job";
private static final String POSTFIX_TRIGGER = "_Trigger";
//静态的任务作业周期,方便其他类使用
static String quartzTestJobCycle="";
//存储该类的实例,Job类通过getInstance()方法得到,算简单的单例模式吧,虽然没有私有的构造方法
private static QuartzTestManagerr instance;
private Scheduler scheduler;

public void run(){
try {
log.info("~~~~~~QuartzTest定时任务调度开始~~~~~~~~");
JobDataMap quartzTestJob = new JobDataMap();
//ReadPropertiesUtil.getCycleName()方法是从properties配置文件中拿到输入参数的值,具体实现在最后说明
String quartzTestJobTime = ReadPropertiesUtil.getCycleName("SCHEDULER_MODELCHANGEIMPACTHISTORY_TIME");
if(!StringUtils.isEmpty(quartzTestJobTime)){
//根据设置的格式判断按月、按日或按小时等时间周期调度
String[] arr = quartzTestJobTime.split("_");
if(arr.length>1) {
quartzTestJobCycle = "month";
} else {
arr = quartzTestJobTime.split(":");
if(arr.length==3){
quartzTestJobCycle = "day";
}else if(arr.length==2){
quartzTestJobCycle = "hour";
}
}
if(!StringUtils.isEmpty(quartzTestJobCycle)){
try{
String conExpress = getConExpree(quartzTestJobCycle, quartzTestJobTime);

if (existJob("quartzTest")) {
removeJob("quartzTest");
addJob("quartzTest", QuartzTestJob.class, conExpress,quartzTestJob);
} else {
addJob("quartzTest", QuartzTestJob.class, conExpress,quartzTestJob);
}
log.info("~~~~~~~~~~~~~~~~~~~~定时任务调度设置成功~~~~~~~~~~~~~~~~~~~~~~~~");
}catch(Exception e){
log.info("~~~~~~~~~~~~~~~~~~~~定时任务调度设置错误~~~~~~~~~~~~~~~~~~~~~~~~");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 新增作业
*
* @param name
*            作业名称
* @param jobClass
*            作业执行类class
* @param cronExpression
*            cron表达式
* @throws MOAppException
*/
@SuppressWarnings({"unchecked" })
public static synchronized void addJob(String name, Class jobClass,
String cronExpression, JobDataMap dataMap){
String jobName = name + POSTFIX_JOB;
String triggerName = name + POSTFIX_TRIGGER;
try {
getInstance().registerJob(jobName, JOB_GROUP_NAME, triggerName,
TRIGGER_GROUP_NAME, jobClass, cronExpression, dataMap);
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 判断指定作业是否存在
*
* @param name
*            作业名称
* @throws MOAppException
*/
public static synchronized boolean existJob(String name) {
String jobName = name + POSTFIX_JOB;
try {
JobDetail jobDetail = getInstance().scheduler.getJobDetail(jobName,
JOB_GROUP_NAME);
return (jobDetail != null);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

public static synchronized ModelChangeImpactManager getInstance()
throws SchedulerException {
if (instance == null) {
instance = new ModelChangeImpactManager();
instance.scheduler = new StdSchedulerFactory().getScheduler();
instance.scheduler.start();
}
return instance;
}

/**
* 删除作业
*
* @param name
*            作业名称
* @throws MOAppException
*/
public static synchronized void removeJob(String name)
throws SchedulerException {
if (existJob(name)) {
try {
String jobName = name + POSTFIX_JOB;
String triggerName = name + POSTFIX_TRIGGER;
Scheduler scheduler = getInstance().scheduler;
scheduler.deleteJob(jobName, JOB_GROUP_NAME);
scheduler.deleteCalendar(triggerName);
} catch (Exception e) {
e.printStackTrace();
}
}
}

private static String getConExpree(String cycle, String runTime) {
if(StringUtils.isEmpty(runTime)){
return null;
}
String con = "";
if (cycle.equals("once")) {
String[] arr = runTime.split(" ");
String[] day = arr[0].split("-");
String[] time = arr[1].split(":");
con = "0 " + time[1] + " " + time[0] + " " + day[2] + " " + day[1]
+ " ?";
}
if (cycle.equals("hour")) {
String[] arr = runTime.split(":");
con = arr[1] + " "+ arr[0] + " * ? * *";
}
if (cycle.equals("day")) {
String[] arr = runTime.split(":");
con = arr[2] + " " + arr[1] + " " + arr[0] + " ? * * ";
}
if (cycle.equals("month")) {
String[] arr = runTime.split("_");
String[] time = arr[1].split(":");
con = time[2] + " " + time[1] + " " + time[0] + " " + arr[0] + " * ? ";
}
System.out.println(con);
return con;
}

@SuppressWarnings({"unchecked" })
private synchronized void registerJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class jobClass,
String cronExpression, JobDataMap dataMap)
throws SchedulerException, ParseException {

JobDetail jobDetail = new JobDetail(jobName, jobGroupName, jobClass);
jobDetail.setJobDataMap(dataMap);
CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);
trigger.setCronExpression(cronExpression);
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
}
}


第三步:编写定时任务具体需要执行功能的业务逻辑类,需要实现 org.quartz.Job接口并复写其public void execute(JobExecutionContext arg0)方法。在该方法中实现任务具体的业务逻辑

public class QuartzTestJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
.......
}
}


附:ReadPropertiesUtil(读取properties文件参数值)

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class ReadPropertiesTest {
private static final String PROPERTIES_NAME = "ReadPropertiesTest.properties";
private static Properties properties = null;
static {
reload();
}
public static Properties getProperties(){
return properties;
}

public static void reload() {
try{
properties = new Properties();
//直接获取该类同文件夹下的properties文件的输入流
//          InputStream fi =ReadPropertiesTest.class.getResourceAsStream(PROPERTIES_NAME) ;
//获取该properties文件的路径后创建inputstream输入流
String path = ReadPropertiesTest.class.getResource(PROPERTIES_NAME).getPath();
InputStream fi = getClassPathResourceAsStream(path);
//java.util.Properties类中的方法传入输入流获取数据
properties.load(fi);
}catch(Exception e){
e.printStackTrace();
}
}

private static InputStream getClassPathResourceAsStream(String name) throws IOException{
//return Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
return new BufferedInputStream(new FileInputStream(name));
}

/**
* 获取properties文件参数的MAP集合
* @return
*/
@SuppressWarnings("rawtypes")
public static List<Map<String,Object>> getRuleCycleMap() throws Exception{
List<Map<String,Object>> list = new LinkedList<Map<String,Object>>();
Enumeration en = properties.keys();
while(en.hasMoreElements()){
Map<String,Object> map = new HashMap<String,Object>();
String key = en.nextElement().toString();
String value = properties.getProperty(key);
map.put("id", key);
//字符串转换编码方式,一边properties里显示的是中文转换后的编码就不用转换,如果直接显示的中文需要转换
map.put("name", new String(value.getBytes("ISO8859-1"), "UTF-8"));
list.add(map);
}
return list;
}


(1)简单实现读取properties文件的参数值


public static void main(String[] args){
//简单的获取参数方法
Properties properties = new Properties();
//注意1:ReadPropertiesTest.properties需要在该类的同文件夹下,才能通过下面的方法得到输入流
InputStream fi =ReadPropertiesTest.class.getResourceAsStream("ReadPropertiesTest.properties");
try {
properties.load(fi);
Enumeration en = properties.keys();
while(en.hasMoreElements()){
String key = en.nextElement().toString();
String value1 = properties.getProperty(key);
//注意2:如果中文显示乱码可以用一下方式转换字符串编码
String value2 = new String(value1.getBytes("ISO8859-1"), "UTF-8");
System.out.println(key+":"+value1);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐