Cron4j 动态读取任务 cron 表达式指令(可手动开始、修改表达式指令、停止等操作)

发布时间:2018-05-06作者:laosun阅读(89102)

Cron4j

Cron4j 动态读取任务 cron 表达式指令(数据库读取),(可手动开始、修改表达式指令后立即生效,可手动及时停止等操作),本测试实在 Jfinal 框架下测试可能会有部分 Jfinal 的代码

    以下代码测试实在 Jfinal 框架上进行测试的,有部分类是Jfinal作者封装的, 但是原理都差不多。主要设计就在 cron4jMap这块,只需要把定时调度类放进去,那么修改这个map中的这个类,就可以实现手动开始、停止等操作了。 当然这个cron4jMap 也可以放到redis中。

    首先我们创建一个表,来存储cron4j的详细信息

    CREATE TABLE `t_cron4j`  (
      `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
      `uuid` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '唯一标识',
      `name` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '定时名称',
      `package_class` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '执行类',
      `cron` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表达式',
      `daemon` int(1) NOT NULL DEFAULT 1 COMMENT '表示调试线程是否设置为守护线程,默认值为 true,守护线程会在 tomcat 关闭时自动关闭',
      `enable` int(1) NOT NULL DEFAULT 1 COMMENT '表示该任务是否有效,默认值为 true,为 false 时该任务无效,不会被调用',
      `stu` int(1) NULL DEFAULT 1 COMMENT '状态1:正常  0:停止禁用  -1:删除',
      `start_execute` int(1) NULL DEFAULT 0 COMMENT '启动后是否立即执行一次(包括添加、修改后立即执行一次)',
      `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '简介说明描述',
      `last_execute_time` timestamp(0) NULL DEFAULT NULL COMMENT '最后一次执行时间',
      `add_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间',
      `update_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '最后一次更新时间',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'cron4j轮询定时管理' ROW_FORMAT = Dynamic;

    首先创建封装类,专门执行cron4j的开始、停止和更新操作

    /** java cron4j 定时调度 **/
    public static final Map<String, Cron4jPlugin> cron4jMap = new HashMap<String, Cron4jPlugin>();
    
    /**
    	 * 添加cron4j调度
    	 * @author sun
    	 * @param cron4j
    	 */
    	public static void addCron4j(TCron4j cron4j){
    		try {
    			/** 这块容易报错 **/
    			Object taskObj = classNewInstance(cron4j.getStr("package_class"));
    			/** 只接受Runnable的定时器 **/
    			if (taskObj instanceof Runnable) {
    				Cron4jPlugin cp = new Cron4jPlugin();
    				Runnable task = (Runnable)taskObj;
    				if(cron4j.getInt("start_execute")==1){//启动立即执行一次
    					Thread t1 = new Thread(new Runnable() {
    						public void run() {
    							task.run();
    						}
    					});
    					t1.start();
    				}
    				cp.addTask(cron4j.getStr("cron"), task, cron4j.getInt("daemon")==1?true:false, cron4j.getInt("enable")==1?true:false);
    				cp.start();
    				/** 放入map中 **/
    				CommonUtils.cron4jMap.put(cron4j.getStr("uuid"), cp);
    			}
    		} catch (InstantiationException e) {
    			e.printStackTrace();
    		} catch (IllegalAccessException e) {
    			e.printStackTrace();
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 更新cron4j任务调度(先删除、后添加的操作原理)
    	 * @author sun
    	 * @param cron4j
    	 */
    	public static void updateCron4j(TCron4j cron4j){
    		deleteCron4j(cron4j);
    		addCron4j(cron4j);
    	}
    	
    	/**
    	 * 删除停止cron4j任务调度
    	 * @author sun
    	 * @param cron4j
    	 */
    	public static void deleteCron4j(TCron4j cron4j){
    		String uuid = cron4j.getStr("uuid");
    		if(CommonUtils.cron4jMap.get(uuid)!=null){
    			Cron4jPlugin cp = CommonUtils.cron4jMap.get(uuid);
    			if(cp!=null){
    				cp.stop();
    			}
    			CommonUtils.cron4jMap.remove(uuid);
    		}
    	}
    	
            /**
    	 * Java 反射
    	 * @author sun
    	 * @param taskClass
    	 * @return
    	 * @throws InstantiationException
    	 * @throws IllegalAccessException
    	 * @throws ClassNotFoundException
    	 */
    	public static Object classNewInstance(String taskClass) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    		if (StrKit.isBlank(taskClass)) {
    			throw new IllegalArgumentException(".class" + " not found.");
    		}
    		taskClass = taskClass.trim();
    		Object taskObj = Class.forName(taskClass).newInstance();
    		return taskObj;
    	}

    以上代码为初始测试代码,实际使用请记得对异常控制一下。


    插入一条数据

    INSERT INTO `t_cron4j`(`id`, `uuid`, `name`, `package_class`, `cron`, `daemon`, `enable`, `stu`, `type`, `start_execute`, `description`, `last_execute_time`, `add_time`, `update_time`) VALUES (1, '1f33830233fc4d00aa6cc5e2d2569555', '测试', 'com.sunjs.job.TestJob', '* * * * *', 1, 1, -1, 2, 1, '测试小李子', '2018-05-04 09:58:12', '2018-05-04 09:58:12', '2018-05-04 16:15:17');

    这条数据的意思就是:每分钟执行一次。

    执行类:com.sunjs.job.TestJob

    package com.sunjs.job;
    public class TestJob implements Runnable {
    
    	public void run() {
    		System.out.println("Hello World!");
    	}
    	
    }


    动态修改cron4j到此就完成了,可以从后台开发出对 t_cron4j 表的增删改查,新增的时候调用增加方法,删除调用删除方法,修改调用修改方法。真正的做到后台动态控制,而不必每次需要修改properties文件,还得重启,挺麻烦的。

    这种做法呢,也需要在系统启动的时候调用一次这个 t_cron4j 表,将所有的生效的数据全部获取出来进行加载。

4 +1

版权声明

 Java  源码

 请文明留言

1 条评论