任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。
业务场景:每天凌晨1点开始,要求对数据库文件备份一次;需在Tomcat启动后自动开始调动任务
实现方式:使用java.util.Timer,创建一个子类继承TimerTask父类来实现
package com.backup;
import java.util.Timer;
import java.util.TimerTask;
/**
* Timer简单测试
*/
public class TimerTest {
public static void main(String[] args) {
MyTimer myTimer = new MyTimer();
Timer timer = new Timer();
long delay = 3 * 1000; //延迟(单位:秒,就是从多少秒开始)
long period = 10 * 1000; //时期(单位:秒,就是每次执行完后间隔多长时间)
//从 3 秒钟之后开始,每隔 10 秒钟执行一次 myTimer
timer.schedule(myTimer, delay, period);
//1 schedule(TimerTask task,Data time)
//安排指定的任务在指定的时间开始执行
//月份要减一
//timer.schedule(backup, new Date(115,8,10,9,54,0));
//2 schedule(TimerTask task, Date firstTime, long period)
// 安排指定的任务在指定的时间开始进行重复的固定延迟执行
//timer.schedule(backup,new Date(115,8,10,10,0,0) ,2000 );
//3schedule(TimerTask task, long delay)
//安排在指定延迟后执行指定的任务。
//timer.schedule(backup, 5000);
//4 schedule(TimerTask task, long delay, long period)
//timer.schedule(backup, 5000, 2000);
//5.每天早上9点出发一次任务
//timer.schedule(backup,new Date(115,8,11,9,0,0) ,24*60*60*1000);
//6.每星期六的凌晨3点出发一次任务
//timer.schedule(backup, new Date(115,8,12,3,0,0),7*24*60*60*1000);
}
}
/**
* Timer测试
* 让MyTimer继承TimerTask,并覆盖run方法
*/
class MyTimer extends TimerTask{
@Override
public void run() {
System.out.println("数据库备份开始");
}
}
属性文件名:dbBackup.properties
# 数据库备份相关配置,这里以导出Oracle中dump文件为例
# Oracle的 sid
exp_oracle_sid=orcl
# 用户名
exp_username=test
# 密码
exp_password=test
# 备份的目录,这里备份到D盘的BackupDatabas目录下
exp_backupPath=D:/BackupDatabas
新建一个工具类,专门负责导出dump的多线程类,类名为DumpFileProcess.java,内容如下
package com.utils;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.SQLExec;
import org.apache.tools.ant.types.EnumeratedAttribute;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class DumpFileProcess {
/**
* 调用cmd进程的方法
* @param expOrImpSyntax
* @return
* @throws InterruptedException
*/
public static boolean exportDatabaseTool(String expOrImpSyntax) throws InterruptedException {
try {
final Process process = Runtime.getRuntime().exec(expOrImpSyntax);
//处理InputStream的线程
new Thread() {
@Override
public void run() {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
processReadLine(in);
}
}.start();
//处理ErrorStream的线程
new Thread() {
@Override
public void run() {
BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));
processReadLine(err);
}
}.start();
if (process.waitFor() == 0) {
return true;
}
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 读取每一行的信息,输出到控制台中
* @param bufferedReader
*/
private static void processReadLine(BufferedReader bufferedReader) {
String line;
try {
while ((line = bufferedReader.readLine()) != null) {
System.out.println("output: " + line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 使用Ant执行SQL语句的测试方法
* @param jdbcDriver
* @param jdbcUrl
* @param userName
* @param password
* @param sqlPath
*/
public static void execSql(String jdbcDriver,String jdbcUrl,String userName,String password,String sqlPath){
SQLExec sqlExec = new SQLExec();
//设置数据库参数
sqlExec.setDriver(jdbcDriver);
sqlExec.setUrl(jdbcUrl);
sqlExec.setUserid(userName);
sqlExec.setPassword(password);
//要执行的脚本
sqlExec.setSrc(new File(sqlPath));
//有出错的语句该如何处理
sqlExec.setOnerror((SQLExec.OnError)(EnumeratedAttribute.getInstance(
SQLExec.OnError.class, "abort")));
sqlExec.setPrint(true); //设置是否输出
//输出到文件 sql.out 中;不设置该属性,默认输出到控制台
//sqlExec.setOutput(new File("src/sql.out"));
sqlExec.setProject(new Project()); // 要指定这个属性,不然会出错
sqlExec.execute();
}
}
- 在Tomcat容器启动时开始数据库备份任务调度,
- Tomcat容器关闭时结束数据库备份任务的调度案例
package com.backup;
import com.utils.DumpFileProcess;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.TimerTask;
public class DataBaseBackup extends TimerTask {
@Override
public void run() {
//实例化属性配置类
Properties properties = new Properties();
InputStream inStream = DataBaseBackup.class.getResourceAsStream("dbBackup.properties");
try {
properties.load(inStream);//加载资源文件
String oracle_sid = properties.getProperty("exp_oracle_sid");
String jdbc_username = properties.getProperty("exp_username");
String jdbc_password = properties.getProperty("exp_password");
String exp_backupPath = properties.getProperty("exp_backupPath");//数据库备份目录
/*
System.out.println("oracle_sid:"+oracle_sid);
System.out.println("jdbc_username:"+jdbc_username);
System.out.println("jdbc_password:"+jdbc_password);
System.out.println("exp_backupPath:"+exp_backupPath);*/
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String f = sdf.format(new Date());
String fileName = exp_backupPath + File.separator + f + ".dmp";
String exportDumpSyntax = "exp " + jdbc_username + "/" + jdbc_password + "@" + oracle_sid + " file=" + fileName;
//文件存放目录不存在则创建
File saveFile = new File(exp_backupPath);
if (!saveFile.exists()) {// 如果目录不存在
saveFile.mkdirs();// 创建文件夹
}
boolean finalResult = DumpFileProcess.exportDatabaseTool(exportDumpSyntax);//导出数据
System.out.println("备份结果:"+finalResult);
} catch (IOException e) {
System.out.println("读取配置信息出错");
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("备份数据库时出现了错误");
e.printStackTrace();
}
}
}
package com.backup;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.Timer;
public class TimerListener implements ServletContextListener {
/**
* 监听web容器启动
*/
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("web容器已启动,开始备份数据库任务");
/**
* 实例化 Timer 计时器
*/
timer = new Timer();
System.out.println("计时器处于准备工作,开始为任务调度分配时间和周期");
//创建任务对象
DataBaseBackup backup = new DataBaseBackup();
//简单测试
long delay = 3 * 1000; //延迟多少秒
long period = 10 * 1000; // 间隔多少秒
//从 3 秒钟之后开始,每隔 10 秒钟执行一次 myTimer
timer.schedule(backup, delay, period);
//1 schedule(TimerTask task,Data time)
//安排指定的任务在指定的时间开始执行
//月份要减一
//timer.schedule(backup, new Date(115,8,10,9,54,0));
//2 schedule(TimerTask task, Date firstTime, long period)
// 安排指定的任务在指定的时间开始进行重复的固定延迟执行
//timer.schedule(backup,new Date(115,8,10,10,0,0) ,2000 );
//3schedule(TimerTask task, long delay)
//安排在指定延迟后执行指定的任务。
//timer.schedule(backup, 5000);
//4 schedule(TimerTask task, long delay, long period)
//timer.schedule(backup, 5000, 2000);
//5.每天早上9点出发一次任务
//timer.schedule(backup,new Date(115,8,11,9,0,0) ,24*60*60*1000);
//6.每星期六的凌晨3点出发一次任务
//timer.schedule(backup, new Date(115,8,12,3,0,0),7*24*60*60*1000);
}
private static Timer timer;
/**
* 监听web容器关闭
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("web容器关闭,结束数据库备份任务");
timer.cancel();
}
}
<!--数据库备份计时器监听-->
<listener>
<listener-class>com.backup.TimerListener</listener-class>
</listener>
启动Tomcat服务器进行测试,完事!