Java自带的Timer实现简单的定时任务调度


文章目录

  • Java自带的Timer实现简单的定时任务调度
  • 1. Java中最简单的一个例子
  • 2. Tomcat容器中任务调度
  • 1. 新建属性文件用来配置导出所需相关配置信息
  • 2. 新建工具类
  • 3. Tomcat启、停时开启、关闭定时任务
  • 4. 启动Tomcat测试


任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。

业务场景:每天凌晨1点开始,要求对数据库文件备份一次;需在Tomcat启动后自动开始调动任务

实现方式:使用java.util.Timer,创建一个子类继承TimerTask父类来实现

1. Java中最简单的一个例子

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("数据库备份开始");
    }
}

2. Tomcat容器中任务调度

1. 新建属性文件用来配置导出所需相关配置信息

属性文件名:dbBackup.properties

# 数据库备份相关配置,这里以导出Oracle中dump文件为例
# Oracle的 sid
exp_oracle_sid=orcl
# 用户名
exp_username=test
# 密码
exp_password=test
# 备份的目录,这里备份到D盘的BackupDatabas目录下
exp_backupPath=D:/BackupDatabas

2. 新建工具类

新建一个工具类,专门负责导出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();
    }
}

3. Tomcat启、停时开启、关闭定时任务

  1. 在Tomcat容器启动时开始数据库备份任务调度,
  2. Tomcat容器关闭时结束数据库备份任务的调度案例
  1. 定义一个DataBaseBackup类让其继承TimerTask
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();
        }

    }
}
  1. 编写一个TimerListener监听类,让其实现ServletContextListener接口
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();
    }
}
  1. 在web.xml中加入TimerListener监听配置
<!--数据库备份计时器监听-->
	<listener>
		<listener-class>com.backup.TimerListener</listener-class>
	</listener>

4. 启动Tomcat测试

启动Tomcat服务器进行测试,完事!