如何在基于Netbeans平台的Java应用程序中创建自动备份功能?

时间:2012-03-23 12:32:23

标签: java netbeans

代码不多,因为我对如何开始有点不知所措。

我正在尝试创建一个备份Derby数据库并存储用户数据的应用程序。我有备份本身的代码,可以手动运行。我想创建一个功能来检查设置文件,并按照适当的时间表(每天,每周,每月)执行备份。我想我可以在启动时检查它,但是如果应用程序正在运行则存在问题,我希望定期检查时间。这个应用程序很可能会连续几天运行。

我也想让用户“睡觉”#34;如果有预定的时间,请备份几个小时。

我可以在启动时调用Thread.Sleep()并每隔X分钟/小时检查一次。同样,如果他们选择睡眠备份。我不确定这是否是最好的方法。我假设任何API调用都可能会这样做,但我想知道我是否在处理这样的线程时遗漏了一些东西。

Netbeans IDE&中是否有任何功能/库?我正在利用的平台,我可以帮助我构建这个功能吗?

由于

1 个答案:

答案 0 :(得分:0)

以下是我实施它的方式。我稍微改变了实现方法,所以这个答案并不完全是问题的措辞。我删除了“睡眠”功能,但使用我提供的代码可以轻松实现它。我部分实现了,我将在下面显示代码。它主要涉及创建一些实现Runnable的类。未显示运行备份的实际代码。无论如何,这将是特定于平台的,所以请按照您的意愿处理。我们正在使用Derby,这就是我们的备份处理方式。

我会按课程和课程分解功能:

DatabaseBackupReminder。此类处理向用户发出的提示,告知用户上次备份后多长时间,并允许他们将提醒暂停X个小时。它本身就是一个线程,因此它可以在其他地方调用并且也可以睡眠,所以它不会一直ping数据库以查看上次备份的运行时间。

public class DatabaseBackupReminder extends Thread

/*****************Variables ****************/
String backupFrequency; //How often to backup? Daily, Monthly, Weekly, or Never
String backupTimeOfDay; //I don't use this, but the idea was to autobackup morning,  
                        //day, or night
boolean backupIsSet = false;    //Have they set a schedule?
Timestamp lastBackupRunTime; //Pulled from our Derby database to see when the backup was run
Timestamp backupScheduleSetTime; //Pulled from the DB to see when the user set the schedule
                                //This is so, if they set it to daily, we will check 24hrs from the set date for
                                //backup validity
Period periodSinceLastBackup; //Using the Joda library, we use this to calculate
boolean backupEverRan; //We check to see if they've ever backed up
                                    //Useful logic for clear dialog purposes.
public enum enumBackupFrequencies {DAILY, WEEKLY, MONTHLY, NEVER} //use a valueOf with the backupFrequency.
//We're using java 1.7, no Switch on strings, this is a workaround
   Herd herd;//Herd is a custom datatype we use, it's basically a wrapper around a Derby table.
/*******************methods***************************************/                                     
    public DatabaseBackupReminder(String backupFrequency, String backupTimeOfDay, Timestamp lastBackupRunTime, Timestamp backupScheduleSetTime, Herd herd) 
    //Constructor
    //Herd is a custom datatype we use, it's basically a wrapper around a Derby table.
    boolean getBackupStillValid() //Checks based on lastBackupRunTime, and backupEverRan to see
    //if we have a valid backup

    public void promptForBackup(Period duration, boolean backupEverRunx) 
        //Take's the duration & has it ever run and displays a message.
        //Something like "It's been 2 weeks, 1 days since your last backup"
        //Not fully implemented, this was scrapped, but I'll explain how I think it should have worked below

    public void run()
    //Main thread for this reminder
    public String timeSinceLastBackupString()
    //Calls it based on objects values, not specific values, see method below
    public String timeSinceLastBackupString(Period duration, boolean backupEverRunx)
    //Constructs the string used in promptForBackup



/********full method code**********/
public DatabaseBackupReminder(String backupFrequency, String backupTimeOfDay, Timestamp lastBackupRunTime, Timestamp backupScheduleSetTime, Herd herd) {
    this.herd = herd;
    if (backupFrequency == null) {
        backupFrequency = "";
    }
    if (backupTimeOfDay == null) {
        backupTimeOfDay = "";
    }
    if (backupScheduleSetTime == null) {
        this.backupScheduleSetTime = new Timestamp(0);
    } else {
        this.backupScheduleSetTime = backupScheduleSetTime;
    }
    this.backupFrequency = backupFrequency;
    this.backupTimeOfDay = backupTimeOfDay;
    if (lastBackupRunTime == null) {
        this.lastBackupRunTime = new Timestamp(0);
    } else {
        this.lastBackupRunTime = lastBackupRunTime;
    }
    periodSinceLastBackup = new Period(this.lastBackupRunTime.getTime(), Calendar.getInstance().getTimeInMillis());
    if (backupFrequency.trim().length() > 1) {
        backupIsSet = true;
    }
    backupEverRan = false;
    if (this.lastBackupRunTime.getTime() != 0) {
        backupEverRan = true;
    }
}

 boolean getBackupStillValid() {
    if (lastBackupRunTime.getTime() > 0) {
        backupEverRan = true;

    } else {
        return false;
    }
    if (backupFrequency.trim().length() > 1) {
        backupIsSet = true;

    }


    if (backupIsSet) {
        switch (enumBackupFrequencies.valueOf(backupFrequency.trim().toUpperCase())) {
            case DAILY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() > 1 || periodSinceLastBackup.getDays() >= 1) {

                    return false;
                }
                break;
            case WEEKLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() >= 1) {
                    return false;

                }
                break;
            case MONTHLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() >= 1) {
                    return false;

                }
                break;
            case NEVER:
        }
    }
    if (backupEverRan) {
        return true;
    } else {
        return false;
    }

}

public void run() {

    if (backupIsSet) {
        switch (enumBackupFrequencies.valueOf(backupFrequency.trim().toUpperCase())) {
            case DAILY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() > 1 || periodSinceLastBackup.getDays() > 1) {

                    promptForBackup(periodSinceLastBackup, backupEverRan);

                }
                break;
            case WEEKLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1 || periodSinceLastBackup.getWeeks() > 1) {
                    promptForBackup(periodSinceLastBackup, backupEverRan);

                }
                break;
            case MONTHLY:
                if (periodSinceLastBackup.getYears() > 1 || periodSinceLastBackup.getMonths() > 1) {
                    promptForBackup(periodSinceLastBackup, backupEverRan);

                }
                break;
            case NEVER:
        }
    }



}
public void promptForBackup(Period duration, boolean backupEverRun) {
    int response;
    long delay = 0;

    response = JOptionPane.showConfirmDialog(null, timeSinceLastBackupString(duration, backupEverRun));
    if (response == JOptionPane.NO_OPTION) {
        //TODO: open "how long to remind" dialog
        BackupSnoozePanel snoozePanel = new BackupSnoozePanel();

        JOptionPane.showMessageDialog(null, snoozePanel);

        switch (snoozePanel.BackupDelayInterval.getSelectedIndex()) {
            case 0:
                delay = 5000; //5 seconds, for testing
                //delay = 60 * 60 * 1000; // 1 hour
                break;
            case 1:
                delay = 10000; //10 seconds, for testing
                //delay = 4 * 60 * 60 * 1000; // 4 hours
                break;
            case 2:
                delay = 15000; //15 seconds, for testing
                //delay = 8 * 60 * 60 * 1000; // 8 hours
                break;
            case 3:
                delay = 20000; //20 seconds, for testing
                ///delay = 12 * 60 * 60 * 1000; // 12 hours
                break;
            case 4:
                delay = 0; //next boot
                break;
        }


    } else {
        //TODO: run backup    
    }
    try {

        if (delay > 0) {
        //TODO: Code to sleep this reminder. Thread.sleep(delay) probably

        }
    } catch (Exception ex) {
        //TODO: something to handle exceptions
    }

}//end promptForBackup

 public String timeSinceLastBackupString(Period duration, boolean backupEverRunx) {

    if (!backupEverRunx) {
        return "The backup has never been run. Would you like to run one?";
    }


    String durationString = "It has been ";
    if (duration.getYears() >= 1) {
        durationString += duration.getYears() + " years";
    }
    if (duration.getMonths() >= 1) {
        durationString += duration.getMonths() + " months";
    }
    if (duration.getWeeks() >= 1) {
        durationString += duration.getWeeks() + " weeks ";
    }
    if (duration.getDays() >= 1) {
        durationString += duration.getDays() + " days";
    }
    durationString += " since your last backup. Would you like to run one?";
    return durationString;
}

public String timeSinceLastBackupString() {
    return timeSinceLastBackupString(periodSinceLastBackup, backupEverRan);



}

DatabaseBackupController。这个类,因为它的名字,控制整个过程。从提醒,到执行实际的备份代码。

public class DatabaseBackupController
/***********variables*************/
String scheduleText; //Daily, Weekly, Monthy, or Never. It's set in our options panel.
String timeText; //Time of day to run the backup, morning, day, or night. As 04:00-12:00 etc…
Timestamp lastBackupRun; //Timestamp from DB (Herd is our abstracted class) from when it was last run.
Timestamp lastBackupRunScheduleSetTime; //Timestamp from DB when the backup was set.
Herd herd; //Herd is a custom datatype we use, it's basically a wrapper around a Derby table.

/***********Method Headers**********/
public DatabaseBackupController(Herd herd) //Constructor
//Sets global variables, based on values in DB
public void setupBackupReminder() 
//calls DatabaseBackupReminder, passes global variables.
public boolean checkBackupReminder()
//Checks to make sure the current backup is valid within the duration since last backup
public void runBackupPrompt() 
//When we are in fact going to backup, calls BackupRunner instance.


/**********full method code****************/
    public DatabaseBackupController(Herd herd) {
    this.herd = herd;
    scheduleText = herd.getBackupSchedule();
    timeText = herd.getBackupTime();
    lastBackupRun = herd.getBackupScheduledLastRun();
    lastBackupRunScheduleSetTime = herd.getBackupScheduledDatetime();
}

public void setupBackupReminder() {
    DatabaseBackupReminder dbReminder = new DatabaseBackupReminder(scheduleText, timeText, lastBackupRun, lastBackupRunScheduleSetTime, herd);
    Thread dbBackupThread = new Thread(dbReminder);

    dbBackupThread.start();
}//end setupBackupReminder

public boolean checkBackupReminder() {
    DatabaseBackupReminder dbReminder = new DatabaseBackupReminder(scheduleText, timeText, lastBackupRun, lastBackupRunScheduleSetTime, herd);
    return dbReminder.getBackupStillValid();
}

public void runBackupPrompt() {
    DatabaseBackupReminder dbReminder = new DatabaseBackupReminder(scheduleText, timeText, lastBackupRun, lastBackupRunScheduleSetTime, herd);
    int response = JOptionPane.showConfirmDialog(null, dbReminder.timeSinceLastBackupString());
    if (response == JOptionPane.YES_OPTION) {
        //NbPreferences.forModule(BackupSettingsPanel.class).putLong("databaseschedullastrun", Calendar.getInstance().getTimeInMillis());
        LoadStatusDialog lsd;
        lsd = null;
        lsd = new LoadStatusDialog(WindowManager.getDefault().getMainWindow(), false, true);
        lsd.setVisible(true);
        Thread br = new Thread(new BackupRunner(herd,lsd));
        br.start();
    }
}
}//end class

Class DbBackupAction处理本地备份方面。我们在本地备份,然后在另一个类的异地发送该文件。 这实现了runnable,因此它将异步处理备份而不会导致整个程序挂起。

class DbBackupAction implements Runnable {

private boolean backupSuccess;

public DbBackupAction() {
    this.backupSuccess = false;
}

public void runBackup() {
}

@Override
public void run() {
    Connection connection = JDBCUtils.getConnection();
    String dbName = NbPreferences.forModule(DatabasePanel.class).get("dbName", "");
    try {
        DerbyUtils.backUpDatabase(connection, dbName);
    } catch (SQLException ex) {
        Exceptions.printStackTrace(ex);
    }
    setBackupSuccess(true);
}

/**
 * @return the backupSuccess
 */
public boolean isBackupSuccess() {
    return backupSuccess;
}

/**
 * @param backupSuccess the backupSuccess to set
 */
public void setBackupSuccess(boolean backupSuccess) {
    this.backupSuccess = backupSuccess;
}
}

BackupRunner处理现场/非现场备份。使用DbBackupAction&& RemoteBackupAction

class BackupRunner implements Runnable {

Herd herd;
LoadStatusDialog lsd; 

BackupRunner(Herd herd, LoadStatusDialog lsd) {
    this.herd = herd;
    this.lsd = lsd;
}

@Override
public void run() {



    DbBackupAction dba = new DbBackupAction();
    Thread dbaThread = new Thread(dba);

    dbaThread.start();
    while (dbaThread.isAlive()) {
        try {
            dbaThread.join();
        } catch (InterruptedException ex) {
            Exceptions.printStackTrace(ex);
        }
    }


    if (dba.isBackupSuccess()) {

        RemoteBackupAction rba = new RemoteBackupAction();
        lsd.setProgressBarIndeterminate(true);
        Thread rbaThread = new Thread(rba);
        rbaThread.start();
        while (rbaThread.isAlive()) {
            try {
                rbaThread.join();
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }
        }



        if (rba.isBackupSuccess()) {


            herd.setBackupScheduledLastRun(new Timestamp(Calendar.getInstance().getTimeInMillis()));
            HerdService hs = new HerdDaoService();
            hs.update(herd);

            EventBus.publish(new RefreshStartScreenEvent());
        }
    }
}
}

RemoteBackupAction处理非现场备份。

class RemoteBackupAction implements Runnable {

Thread thread;
LoadStatusDialog lsd;
File backupFile;
Pref pref;
private boolean backupSuccess;

public RemoteBackupAction() {
    backupSuccess = false;
}

public void runThread() {

                backupSuccess = true;

                try {
                    DerbyUtils.remoteBackupDatabase(backupFile);
                } catch (SQLException ex) {
                    JOptionPane.showMessageDialog(null,
                            "This option is not available when working offline.");
                    System.out.println("SQLExcption: " + ex);
                    backupSuccess = false;
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(null,
                            "Unable to connection to ftp site for remote backup.");
                    System.out.println("IOExcption: " + ex);
                    backupSuccess = false;
                }



}

public void startOffsiteBackup() {
    pref = CentralLookup.getDefault().lookup(Pref.class);
    System.out.println("pref.isOnline(): " + pref.isOnline());
    if (!pref.isOnline()) {
        JOptionPane.showMessageDialog(null,
                "This option is not available when working offline.");
        return;
    }

    File[] files = DerbyUtils.getListOfBackups();
    if ((files == null) || (files.length < 1)) {
        JOptionPane.showMessageDialog(null,
                "There are no backup files available for upload. "
                + "Please create a local backup.");
        return;
    }
    Backup[] backups = new Backup[files.length];
    if (files.length > 0) {
        Date[] dates = new Date[files.length];
        String[] herdCodes = new String[files.length];
        SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
        for (int i = 0; i < files.length; i++) {
            try {
                String[] splitFileName = files[i].getName().split("_");
                herdCodes[i] = splitFileName[0];
                dates[i] = inFormat.parse(splitFileName[1].split("//.")[0]);
                backups[i] = new Backup(herdCodes[i], files[i], files[i].getName(), dates[i]);
            } catch (ParseException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    } else {
        System.out.println("no backup files yet");
    }

    Arrays.sort(backups, Collections.reverseOrder());

    if (backups[0] != null) {

        this.backupFile = backups[0].getFile();
    } else {
        // Cancel button selected
        return;
    }

    runThread();
}

/**
 * @return the backupSuccess
 */
public boolean isBackupSuccess() {
    return backupSuccess;
}

@Override
public void run() {
    startOffsiteBackup();
}