SSM动态增加定时任务及定时数据库备份

记得第一步将mysql的bin目录加入path系统变量!

pom依赖:

<!-- 定时任务 -->
<dependency>
   <groupId>org.quartz-scheduler</groupId>
   <artifactId>quartz</artifactId>
</dependency>
<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
</dependency>

spring-mvc.xml开头处增加:

<task:annotation-driven executor="executor" scheduler="scheduler" />

创建spring-schedule.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
	
	<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="configLocation" value="classpath:quartz-production.properties"></property>
	</bean>
</beans>

创建quartz-production.properties:

org.quartz.scheduler.skipUpdateCheck = true
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 
org.quartz.threadPool.threadCount = 5 
org.quartz.threadPool.threadPriority = 4
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

application.properties中添加:

backup.isQuartz=true
backup.core=6 6 6 * * ? 
backup.filepath=x:\\xxx\\xxx

创建MessageQuartzStartModel.java:

package com.fuhai.platform.utils.message.web.controller;

public class MessageQuartzStartModel {

	private boolean isStart;
	
	private String coreStr;
	
	public boolean isStart() {
		return isStart;
	}

	public void setStart(boolean isStart) {
		this.isStart = isStart;
	}

	public String getCoreStr() {
		return coreStr;
	}

	public void setCoreStr(String coreStr) {
		this.coreStr = coreStr;
	}
}

创建QuartzManager.java:

package com.fuhai.platform.utils.message.quartz;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzManager {
	private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

	/**
	 * @Description: 添加一个定时任务
	 * 
	 * @param jobName          任务名
	 * @param jobGroupName     任务组名
	 * @param triggerName      触发器名
	 * @param triggerGroupName 触发器组名
	 * @param jobClass         任务
	 * @param cron             时间设置,参考quartz说明文档
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
			Class jobClass, String cron) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			// 任务名,任务组,任务执行类
			JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();

			// 触发器
			TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
			// 触发器名,触发器组
			triggerBuilder.withIdentity(triggerName, triggerGroupName);
			triggerBuilder.startNow();
			// 触发器时间设定
			triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
			// 创建Trigger对象
			CronTrigger trigger = (CronTrigger) triggerBuilder.build();

			// 调度容器设置JobDetail和Trigger
			sched.scheduleJob(jobDetail, trigger);

			// 启动
			if (!sched.isShutdown()) {
				sched.start();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 修改一个任务的触发时间
	 * 
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName      触发器名
	 * @param triggerGroupName 触发器组名
	 * @param cron             时间设置,参考quartz说明文档
	 */
	public static void modifyJobTime(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
			String cron) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
			CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}

			String oldTime = trigger.getCronExpression();
			if (!oldTime.equalsIgnoreCase(cron)) {
				/** 方式一 :调用 rescheduleJob 开始 */
				// 触发器
				TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
				// 触发器名,触发器组
				triggerBuilder.withIdentity(triggerName, triggerGroupName);
				triggerBuilder.startNow();
				// 触发器时间设定
				triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
				// 创建Trigger对象
				trigger = (CronTrigger) triggerBuilder.build();
				// 方式一 :修改一个任务的触发时间
				sched.rescheduleJob(triggerKey, trigger);
				/** 方式一 :调用 rescheduleJob 结束 */

				/** 方式二:先删除,然后在创建一个新的Job */
				// JobDetail jobDetail =
				// sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
				// Class<? extends Job> jobClass = jobDetail.getJobClass();
				// removeJob(jobName, jobGroupName, triggerName,
				// triggerGroupName);
				// addJob(jobName, jobGroupName, triggerName, triggerGroupName,
				// jobClass, cron);
				/** 方式二 :先删除,然后在创建一个新的Job */
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 移除一个任务
	 * 
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName
	 * @param triggerGroupName
	 */
	public static void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();

			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

			sched.pauseTrigger(triggerKey);// 停止触发器
			sched.unscheduleJob(triggerKey);// 移除触发器
			sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description:启动所有定时任务
	 */
	public static void startJobs() {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			sched.start();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description:关闭所有定时任务
	 */
	public static void shutdownJobs() {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			if (!sched.isShutdown()) {
				sched.shutdown();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}

创建SendMessageQuartzTaskListener.java:


package com.fuhai.platform.utils.message.quartz;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import com.fuhai.platform.utils.message.web.controller.MessageQuartzStartModel;

@Service
public class SendMessageQuartzTaskListener implements ApplicationListener<ContextRefreshedEvent>{

	@Value("${backup.isQuartz:false}")
	private boolean backupIsQuartz; // 是否开启数据库备份自动任务
	@Value("${backup.core:6 6 6 * * ?}")
	private String backupCore; // 自动任务时间


	
	private boolean isInit = false; // 防止启动时加载两次
	
	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		if (!this.isInit) {
			this.isInit = true;
			MessageQuartzStartModel backupModel = new MessageQuartzStartModel();
			backupModel.setStart(backupIsQuartz);
			backupModel.setCoreStr(backupCore);
			SendMessageQuartzTaskManager.startTask(backupModel);
		}
	}


}

创建SendMessageQuartzTaskManager.java:

package com.fuhai.platform.utils.message.quartz;

import com.fuhai.platform.utils.message.web.controller.MessageQuartzStartModel;

public class SendMessageQuartzTaskManager {

	private static String JOB_GROUP_NAME = "MESSAGE_SEND_GROUP";
	private static String TRIGGER_GROUP_NAME = "MESSAGE_SEND_JOB_GROUP";
	private static String BACKUP_SEND_JOB_NAME = "数据库备份发送定时任务";
	private static String BACKUP_SEND_TRIGGER_NAME = "数据库备份发送定动态任务触发器";


	/**
	 * 
	 * @Title: startTask
	 * @Description:(装载并启动自动任务)
	 * @author ch
	 * @return void 返回类型
	 */
	public static void startTask(MessageQuartzStartModel backupModel) {
		
		if (backupModel.isStart()) {
			// 装载数据库备份自动发送任务
			QuartzManager.addJob(BACKUP_SEND_JOB_NAME, JOB_GROUP_NAME, BACKUP_SEND_TRIGGER_NAME, TRIGGER_GROUP_NAME,
					com.xxxxxxxxxx.quartz.SendBackupQuartzTask.class, backupModel.getCoreStr());
		}

		if (backupModel.isStart()) {
			QuartzManager.startJobs();
		}
	}

	/**
	 * @Title: shutdownTask
	 * @Description:(卸载自动任务)
	 * @author ch
	 * @return void 返回类型
	 */
	public static void shutdownTask() {
		// 卸载自动任务
		QuartzManager.removeJob(BACKUP_SEND_JOB_NAME, JOB_GROUP_NAME, BACKUP_SEND_TRIGGER_NAME, TRIGGER_GROUP_NAME);
		QuartzManager.shutdownJobs();
	}
}

创建SendBackupQuartzTask.java:


package com.fuhai.platform.utils.message.quartz;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;

/**
 * 
 * @author ch
 *
 * @Date: 2020/02/25 15:40:10
 *
 */
@Component
public class SendBackupQuartzTask implements Job {
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
        //这里放逻辑
        //BackUpUtil.getInstance().BackUpToFile();
	}

}

数据库备份工具类BackUpUtil.java:

package com.fuhai.platform.utils.message.quartz;

import com.fuhai.platform.core.encrypt.ThreeDESUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 数据库备份工具类
 */

public class BackUpUtil {

    public static BackUpUtil instance;
    private static String backupFilepath;

    public static BackUpUtil getInstance() {
        if (backupFilepath==null||backupFilepath.length()==0){
            ResourceBundle rb = ResourceBundle.getBundle("application-dev"); //其中“application-dev”为project.properties文件的前缀名,在方法中获取时不需要添加.properties结尾
            backupFilepath = rb.getString("backup.filepath");//uploadPath.path为值对应的键
        }
        if(instance == null){
            instance = new BackUpUtil();
        }
        return instance;
    }



    /**
     * 获取已经备份的文件列表
     * @return
     */
    public List<Map<String,Object>> getBackupFilesInfo(){
        List<Map<String,Object>> infolist = new ArrayList<Map<String, Object>>();
        List<File> list = getFileSort(backupFilepath);
        Map<String,Object> map;
        for (File file:list){
            map = new HashMap<String, Object>(5);
            map.put("fileName",file.getName());
            map.put("fileSize",renderFileSize(file.length()));
            map.put("createTime", new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format(new Date(file.lastModified())));
            infolist.add(map);
        }
        return infolist;
    }

    /**
     * 下载备份文件
     * @param fileName
     * @param request
     * @param response
     */
    public void downloadBackupFile(String fileName,HttpServletRequest request,HttpServletResponse response){
        if (fileName!=null&&fileName.endsWith(".sql")&&!fileName.contains("/")&&!fileName.contains("\\")){
            File file = new File(backupFilepath+File.separator+fileName);
            try{
                if (file.exists()){

                    // 如果是IE浏览器,则用URLEncode解析
                    if (isMSBrowser(request)) {
                        fileName = URLEncoder.encode(fileName, "UTF-8");
                        fileName = fileName.replace("+", " ");
                    } else {// 如果是谷歌、火狐则解析为ISO-8859-1
                        fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
                    }

                    response.setContentType("application/x-msdownload");
                    response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
                    response.setCharacterEncoding("UTF-8");
                    response.setHeader("Content-Length", String.valueOf(file.length()));
                    BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                    byte[] buff = new byte[(int) file.length()];
                    int offset = 0;
                    int numRead = 0;
                    while (offset < buff.length && (numRead = bis.read(buff, offset, buff.length - offset)) >= 0) {
                        offset += numRead;
                    }
                    bis.close();
                    bos.write(buff);
                    bos.close();
                }else{
                    response.getWriter().print("This file does not exist!");
                }
            }catch (Exception e){}
        }
    }

    public boolean isMSBrowser(HttpServletRequest request) {
        String[] IEBrowserSignals = { "MSIE", "Trident", "Edge" };
        String userAgent = request.getHeader("User-Agent");
        for (String signal : IEBrowserSignals) {
            if (userAgent.contains(signal)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 备份数据库到一个文件
     */
    public void BackUpToFile(){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                            List<File> list = getFileSort(backupFilepath);
                            if (list.size()>30){//删除30以上的旧的sql数据
                                try{
                                    for (int i = 30; i < list.size(); i++) {
                                        list.get(i).delete();
                                    }
                                }catch (Exception e){
                                    System.out.println("backup error:old SQL files removal error!");
                                }
                            }


                            String hostIP = "127.0.0.1";
                            String port = "3306";
                            String databaseName = "db_name";
                            String userName = "root";
                            String password = "123456";

                            Process process = Runtime.getRuntime().exec(" mysqldump -h" + hostIP +
                                    " -p"+port+" -u" + userName + " -p" + password + " --set-charset=UTF8 " + databaseName);
                            InputStream inputStream = process.getInputStream();


                            String fileName = "数据库_"+databaseName+"_"+ new SimpleDateFormat( "yyyyMMdd_HHmmss" ).format(new Date())+".sql";
                            File dir = new File(backupFilepath);
                            if (!dir.exists()){
                                dir.mkdirs();
                            }
                            FileOutputStream out = new FileOutputStream(backupFilepath+File.separator+fileName);
                            int len = 0;
                            byte[] buffer = new byte[1024];

                            while ((len = inputStream.read(buffer)) > 0) {
                                out.write(buffer, 0, len);
                            }
                            inputStream.close();
                            out.close();
                            File backupFile = new File(backupFilepath+File.separator+fileName);
                            if (backupFile.length()>2000){
                                System.out.println("backup msg:backup success! "+new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format(new Date()));
                            }else{
                                System.out.println("backup error:The backup file is too small, please check if the backup was successful!? "+new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format(new Date()));
                            }
                    }catch (Exception e){
                        e.printStackTrace();
                        System.out.println("backup error:Automatic database backup failed "+new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format(new Date())+" , error msg:"+e.toString());
                    }
                }
            }).start();
    }


    /**
     * 文件大小格式化
     * @param fileSize
     * @return
     */
    public String renderFileSize(Long fileSize) {
        String[] arr = {"Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
        float srcsize = Float.valueOf(fileSize);
        int index = (int) (Math.floor(Math.log(srcsize) / Math.log(1024)));
        double size = srcsize / Math.pow(1024, index);
        size = Double.valueOf(new DecimalFormat("#.00").format(size));
        return size + arr[index];
    }

    /**
     * 获取目录下所有文件(按时间排序)
     *
     * @param path
     * @return
     */
    public static List<File> getFileSort(String path) {

        List<File> list = getFiles(path, new ArrayList<File>());

        if (list != null && list.size() > 0) {

            Collections.sort(list, new Comparator<File>() {
                public int compare(File file, File newFile) {
                    if (file.lastModified() < newFile.lastModified()) {
                        return 1;
                    } else if (file.lastModified() == newFile.lastModified()) {
                        return 0;
                    } else {
                        return -1;
                    }
                }
            });
        }
        return list;
    }

    /**
     *
     * 获取目录下所有文件
     *
     * @param realpath
     * @param files
     * @return
     */
    public static List<File> getFiles(String realpath, List<File> files) {

        File realFile = new File(realpath);
        if (realFile.isDirectory()) {
            File[] subfiles = realFile.listFiles();
            for (File file : subfiles) {
                if (file.isDirectory()) {
                    getFiles(file.getAbsolutePath(), files);
                } else {
                    files.add(file);
                }
            }
        }
        return files;
    }

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值