JFinal+Quartz动态任务调度控制台
来源:互联网 发布:pla 算法初始化 编辑:程序博客网 时间:2024/03/28 18:07
前言】因为项目需要后台动态调度远程服务的任务,其中动态调度选用Quartz调度框架,远程服务还是沿用原来的Hessian,整合到JFinal后台(客户端)。本文主要记录JFinal下的Quartz控制台搭建,实现任务新建、修改和启停基本功能。【正文】
参考资料(来源:JFinal中使用QuartzManager实现动态定时任务)感谢JFinal社区@wangqian0628
maven依赖(其他的就是JFinal项目通用依赖)
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version></dependency>
根据实际需求,对参考资料做了修改,以下是修改后的工具类:
package top.rushpeak.edu03.admin.util;import static org.quartz.CronScheduleBuilder.cronSchedule;import static org.quartz.JobBuilder.newJob;import static org.quartz.TriggerBuilder.newTrigger;import java.util.List;import org.apache.log4j.LogManager;import org.apache.log4j.Logger;import org.quartz.Job;import org.quartz.JobDetail;import org.quartz.JobKey;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.Trigger;import org.quartz.TriggerKey;import org.quartz.impl.StdSchedulerFactory;import com.jfinal.plugin.activerecord.Db;import com.jfinal.plugin.activerecord.Record;import top.rushpeak.edu03.admin.job.DynamicJob;//这个是后面的任务实现类public class QuartzManager { private Logger log = LogManager.getLogger(QuartzManager.class); private Scheduler scheduler = null; public QuartzManager() { try { scheduler = new StdSchedulerFactory().getScheduler(); log.info("初始化调度器 "); } catch (SchedulerException ex) { log.error("初始化调度器=> [失败]:" + ex.getLocalizedMessage()); } } //初始化启动任务 public void initJob(){ List<Record> jobs = Db.find("SELECT * FROM job_manager WHERE 1=1 AND is_enabled = 'Y'"); for(Record job:jobs){ if("Y".equals(job.getStr("is_enabled"))){ String className = job.getStr("class"); Class<? extends Job> jobClazz = null; try { jobClazz = Class.forName(className).asSubclass(Job.class); } catch (Exception e) { System.out.println(className+"没有继承job,e=="+e); log.error(className+"没有继承job,e=="+e); continue; } String name = job.getStr("name"); String group = job.getStr("group"); String cronExpression = job.getStr("cron_expression"); this.addJob(name, group, jobClazz, cronExpression); } } this.start(); } //添加任务 public void addJob(String name, String group, Class<? extends Job> clazz, String cronExpression) { try { // 构造任务 JobDetail job = newJob(clazz).withIdentity(name, group).build(); // 构造任务触发器 Trigger trg = newTrigger().withIdentity(name, group).withSchedule(cronSchedule(cronExpression)).build(); // 将作业添加到调度器 scheduler.scheduleJob(job, trg); log.info("创建作业=> [作业名称:" + name + " 作业组:" + group + "] "); System.out.println("创建作业=> [作业名称:" + name + " 作业组:" + group + "] "); } catch (SchedulerException e) { e.printStackTrace(); log.error("创建作业=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]"); } } //移除任务 public void removeJob(String name, String group) { try { TriggerKey tk = TriggerKey.triggerKey(name, group); scheduler.pauseTrigger(tk);// 停止触发器 scheduler.unscheduleJob(tk);// 移除触发器 JobKey jobKey = JobKey.jobKey(name, group); scheduler.deleteJob(jobKey);// 删除作业 log.info("删除作业=> [作业名称:" + name + " 作业组:" + group + "] "); System.out.println("删除作业=> [作业名称:" + name + " 作业组:" + group + "] "); } catch (SchedulerException e) { e.printStackTrace(); log.error("删除作业=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]"); } } public void start() { try { scheduler.start(); log.info("启动调度器 "); System.out.println("启动调度器 "); } catch (SchedulerException e) { e.printStackTrace(); log.error("启动调度器=> [失败]"); } } public void shutdown() { try { scheduler.shutdown(); log.info("停止调度器 "); System.out.println("停止调度器 "); } catch (SchedulerException e) { e.printStackTrace(); log.error("停止调度器=> [失败]"); } } //测试 public static void main(String[] args) throws InterruptedException{ QuartzManager qm = new QuartzManager(); String name = "DynamicJobName"; String group = "DynamicJobGroup"; String cronExpression = "*/3 * * * * ?"; String className = "top.rushpeak.edu03.admin.job.DynamicJob"; Class<? extends Job> jobClazz = null; try { jobClazz = Class.forName(className).asSubclass(Job.class); } catch (Exception e) { System.out.println(className+"没有继承job,e=="+e); } if(jobClazz==null){ System.exit(0); } qm.addJob(name, group, jobClazz, cronExpression); qm.start(); Thread.sleep(7000); qm.removeJob(name, group); Thread.sleep(3000); String name2 = "DynamicJobName2"; String group2 = "DynamicJobGroup2"; String cronExpression2 = "*/3 * * * * ?"; qm.addJob(name2, group2, DynamicJob.class, cronExpression2); Thread.sleep(9000); qm.shutdown(); }}
任务接口、实现类
package top.rushpeak.edu03.admin.job;import org.apache.log4j.Logger;public class AbstractJob { public static final Logger LOG = Logger.getLogger(AbstractJob.class);}
package top.rushpeak.edu03.admin.job;import java.util.Date;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import top.rushpeak.edu03.admin.util.DateUtil;public class DynamicJob3 implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("任务3:"+DateUtil.dateFormat(new Date(), "yyyyMMddHHmmss")); }}
上面基本配置完成后,下面就是业务了。
任务表
CREATE TABLE `job_manager` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '' COMMENT '任务名', `group` varchar(50) NOT NULL DEFAULT '' COMMENT '组名', `clazz` varchar(50) NOT NULL DEFAULT '' COMMENT '类名', `cron_expression` varchar(50) NOT NULL DEFAULT '' COMMENT '定时表达式', `is_enabled` char(1) NOT NULL DEFAULT 'N' COMMENT '是否开启', PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`,`group`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
BaseController父类,通用方法
import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.log4j.Logger;import com.jfinal.core.Controller;public class BaseController extends Controller { public static final Logger LOG = Logger.getLogger(BaseController.class); @SuppressWarnings("rawtypes") protected Map<String, Object> buildPagination(List list, Integer count) { return buildPagination(list, count, null); } @SuppressWarnings("rawtypes") protected Map<String, Object> buildPagination(List list, Integer count, List<Map<String, Object>> footer) { Map<String, Object> map = new HashMap<String, Object>(); map.put("total", count); map.put("rows", list); if (footer != null) map.put("footer", footer); return map; }}
页面业务类
import java.sql.SQLException;import org.quartz.Job;import com.alibaba.druid.util.StringUtils;import com.jfinal.plugin.activerecord.Db;import com.jfinal.plugin.activerecord.IAtom;import com.jfinal.plugin.activerecord.Page;import com.jfinal.plugin.activerecord.Record;import com.jfinal.render.JsonRender;import top.rushpeak.edu03.admin.util.QuartzManager;import top.rushpeak.edu03.admin.util.Result;public class JobmanageController extends BaseController { public void index() { render("index.html"); } //获取任务信息 public void post(){ int pageNum = getParaToInt("page", 1); int rows = getParaToInt("rows", 30); String whereSql = " where 1=1 "; pageNum = pageNum > 0 ? pageNum : 1; Page<Record> page = Db.paginate(pageNum, rows, "select * ", " from job_manager" + whereSql + "order by id desc"); setAttrs(buildPagination(page.getList(), page.getTotalRow())); render(new JsonRender().forIE()); } //新增任务 public void add(){ System.out.println("add"); String id = getPara("id"); String name = getPara("name"); String group = getPara("group"); String clazz = getPara("clazz"); String cron_expression = getPara("cron_expression"); String is_enabled = getPara("is_enabled"); try { Class<? extends Job> jobClazz = Class.forName(clazz).asSubclass(Job.class); Record r = new Record(); r.set("name", name); r.set("group", group); r.set("clazz", clazz); r.set("cron_expression", cron_expression); r.set("is_enabled", "N"); if(StringUtils.isEmpty(id)){//新增 Db.save("job_manager", "id",r); }else{//修改 r.set("id", id); Db.update("job_manager", "id",r); } } catch (Exception e) { LOG.error("e=="+e); renderJson(Result.error("异常")); } renderJson(Result.OK); } //启用关停 public void delete(){ try { final String id = getPara("id"); final Record r = Db.findById("job_manager", id); if(r!=null){ //事务管理,确保数据库状态与任务管理器一致 boolean bl = Db.tx(new IAtom() { @Override public boolean run() throws SQLException { String name = r.getStr("name"); String group = r.getStr("group"); String clazz = r.getStr("clazz"); String cron_expression = r.getStr("cron_expression"); String is_enabled = r.getStr("is_enabled"); String change_enable = "N".equals(is_enabled)?"Y":"N"; r.set("is_enabled", change_enable); Db.update("job_manager", "id", r); Class<? extends Job> jobClazz; try { jobClazz = Class.forName(clazz).asSubclass(Job.class); } catch (ClassNotFoundException e) { LOG.error("job类异常:"+e); throw new RuntimeException("job类异常"); } QuartzManager qm = new QuartzManager(); if("Y".equals(r.getStr("is_enabled"))){ try { qm.removeJob(r.getStr("name"), r.getStr("group")); } catch (Exception e) { LOG.error("removeJob_err:"+e); } qm.addJob(r.getStr("name"), r.getStr("group"), jobClazz, r.getStr("cron_expression")); }else{ qm.removeJob(r.getStr("name"), r.getStr("group")); } return true; } }); } } catch (Exception e) { LOG.error("e=="+e); renderJson(Result.error("异常")); } renderJson(Result.OK); } public void get(){ Record r = null; try { String id = getPara("id"); r = Db.findById("job_manager", id); } catch (Exception e) { LOG.error("e=="+e); renderJson(Result.error("异常")); } renderJson(Result.success(r)); }}
不规范的html,试验用的页面很粗糙。js和css很多走本地,没用cdn,不能直接用,抱歉,主题代码还是可以用的。
<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>JOB测试</title><link rel="icon" href="/favicon.ico" type="image/x-icon" /><link rel="bookmark" href="/favicon.ico" type="image/x-icon" /><link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /><meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"><link rel="stylesheet" href="/dist/css/bootstrap/bootstrap.min.css"><link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css"><link rel="stylesheet" href="https://cdn.bootcss.com/ionicons/2.0.1/css/ionicons.min.css"><link rel="stylesheet" href="/dist/css/adminlte/AdminLTE.min.css"><link rel="stylesheet" href="dist/css/skins/skin-blue.min.css"><link rel="stylesheet" type="text/css" href="/dist/easyui/themes/gray/easyui.css"></head><script src="/dist/plugins/jQuery/jquery-2.2.3.min.js"></script><script src="/dist/js/bootstrap.min.js"></script><script src="/dist/js/app.min.js"></script><script src="https://cdn.bootcss.com/layer/3.0.1/layer.min.js"></script><script type="text/javascript" src="/dist/easyui/jquery.easyui.min.js"></script><script src="http://code.jquery.com/jquery-migrate-1.1.1.js"></script><script type="text/javascript"> $(document) .ready( function() { var _toolbar = [ { id : 'btnRefresh', text : '刷新', iconCls : 'icon-reload', handler : function() { refresh(); } }, '-', { id : 'btnAddItem', iconCls : 'icon-add', text : '添加', handler : function() { add(); } } ]; $('#datagrid') .datagrid( { title : '任务调度管理', url : '/jobmanage/post', toolbar : _toolbar, columns : [ [ { field : 'id', title : 'ID', width : 50, align : 'center' }, { field : 'name', title : '任务名', width : 100, align : 'center' }, { field : 'group', title : '任务组名', width : 100, align : 'center' }, { field : 'clazz', title : '类全名', width : 300, align : 'center' }, { field : 'cron_expression', title : '定时表达式', width : 100, align : 'center' }, { field : 'is_enabled', title : '是否启动', width : 100, align : 'center' }, { field : 'action', title : '操作', width : 150, align : 'center', formatter : function( value, row,index) { var a = "<a href='javascript:update("+row.id+")'>修改</a> "; var b = "<a href='javascript:deleteItem("+row.id+")'>启停</a>"; return a + " " +b; } } ] ], pagination : true, rownumbers : true, pageSize : 20, rowStyler : function(index, row) { return "height:100px;"; }, singleSelect : true }); $(document).on("click", ".addSubmitBtn", addSubmit); $(document).on("click", ".updateBtn", update); $(document).on("click", ".delBtn", deleteItem); }); /* 刷新 */ function refresh() { $('#datagrid').datagrid('reload'); } /* 添加 */ function add() { $("#showAddId").hide(); $("#myModalLabel").text("新增"); $("#add_id").val(""); $("#add_name").val(""); $("#add_group").val(""); $("#add_clazz").val(""); $("#add_cron_expression").val(""); $("#add_is_enabled").val(""); $("#myModal").modal("show"); } /* 更新 */ function update(id) { console.log("update"); /* var id = $(this).data("id"); */ var id = id; $("#myModalLabel").text("修改"); $.post("/jobmanage/get", { id : id }, function(data) { if (data.result == "success") { $("#add_id").val(data.data.id); $("#add_name").val(data.data.name); $("#add_group").val(data.data.group); $("#add_clazz").val(data.data.clazz); $("#add_cron_expression").val(data.data.cron_expression); $("#add_is_enabled").val(data.data.is_enabled); } else { alert(data.message); } }); $("#showAddId").show(); $("#myModal").modal("show"); } /* 添加修改提交 */ function addSubmit() { var req_params = {}; req_params.id = $("#add_id").val(); req_params.name = $("#add_name").val(); req_params.group = $("#add_group").val(); req_params.clazz = $("#add_clazz").val(); req_params.cron_expression = $("#add_cron_expression").val(); req_params.is_enabled = $("#add_is_enabled").val(); $.post('/jobmanage/add', req_params, function(data) { if (data.result == "success") { var title = $("#myModalLabel").text(); layer.msg(title + "完成"); $("#myModal").modal("hide"); refresh(); } else { alert(data.message); } }); } /* 启停 */ function deleteItem(id) { /* var id = $(this).data("id"); */ if (!window.confirm("确认启停")) { return; } $.post("/jobmanage/delete", { id : id }, function(data) { if (data.result == "success") { layer.msg("启停完成"); refresh(); } else { alert(data.message); } }); } /* 搜索 */ function search() { var id = $('#search_id').val(); var name = $('#search_name').val(); var group = $('#search_group').val(); var is_enabled = $('#search_is_enabled').val(); $('#datagrid').datagrid('load', { "id" : id, "name" : name, "group" : group, "is_enabled" : is_enabled }); }</script><body> <div id="p1" class="easyui-panel" title="查询" style="padding: 10px; background: #fafafa; margin-bottom: 10px;" iconCls="icon-sum" closable="false" collapsible="false" minimizable="false" maximizable="false"> ID:<input id="search_id" name="search_id" class="txt_fm_mmp easyui-validatebox search"> 任务名:<input id="search_name" name="search_name" class="txt_fm_mmp easyui-validatebox search"> 任务组名:<input id="search_group" name="search_group" class="txt_fm_mmp easyui-validatebox search"> 是否启动:<input id="search_is_enabled" name="search_is_enabled" class="txt_fm_mmp easyui-validatebox search"> <a href="javascript:search();" class="easyui-linkbutton" plain="true" iconCls="icon-search">搜索</a> </div> <table id="datagrid"></table> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" data-backdrop="false"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title" id="myModalLabel">新增</h4> </div> <div class="modal-body"> <form class="form-horizontal"> <div class="form-group" style="display: none" id="showAddId"> <label for="add_id" class="col-sm-2 control-label">id</label> <div class="col-sm-10"> <input type="text" class="form-control" id="add_id" placeholder="ID" readonly> </div> </div> <div class="form-group"> <label for="add_name" class="col-sm-2 control-label">任务名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="add_name" placeholder="任务名" required> </div> </div> <div class="form-group"> <label for="add_group" class="col-sm-2 control-label">任务组名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="add_group" placeholder="任务组名" required> </div> </div> <div class="form-group"> <label for="add_clazz" class="col-sm-2 control-label">类全名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="add_clazz" placeholder="类全名" required> </div> </div> <div class="form-group"> <label for="add_cron_expression" class="col-sm-2 control-label">定时表达式</label> <div class="col-sm-10"> <input type="text" class="form-control" id="add_cron_expression" placeholder="定时表达式" required> </div> </div> <div class="form-group" hidden="true"> <label class="col-sm-2 control-label">是否启动</label> <div class="col-sm-10"> <select class="form-control" id="add_is_enabled"> <option value="N">否</option> <option value="Y">是</option> </select> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary addSubmitBtn">提交</button> </div> </div> </div> </div></body></html>
配置jfinal路由,这个根据项目结构写的,就没必要放我的码子。
完成以上,便可以开启localhost模式了。
阅读全文
0 0
- JFinal+Quartz动态任务调度控制台
- JFinal+Quartz动态任务调度控制台
- jfinal任务调度quartz(cron)
- Spring+quartz 动态任务调度
- Spring + Quartz动态任务调度
- jfinal+quartz定时任务
- Quartz Job & Spring 动态任务调度
- spring+quartz实现动态任务调度
- Jfinal+quartz实现作业调度
- Jfinal+quartz实现作业调度
- 动态Quartz任务调度(Spring结合Quartz)
- Spring + Quartz任务调度实战之动态作业调度
- Spring + Quartz任务调度实战之动态作业调度
- Spring + Quartz任务调度实战之动态作业调度
- Quartz[时间任务]之Jfinal
- Jfinal实现定时任务调度
- 【Quartz】Quartz任务调度入门
- Quartz任务调度
- pyCuda中的坑
- CSS样式之背景样式
- 串口通讯协议
- C++水仙花数的求法
- Ocelot——初识基于.Net Core的API网关
- JFinal+Quartz动态任务调度控制台
- 图像处理之特征提取:HOG特征简单梳理
- Hangfire在ASP.NET CORE中的简单实现
- HAVING&WHERE
- C语言 机器字节序、大小端的判断与修改
- idea Commit Changes Dialog local changes refresh
- 链队的一些操作
- C++构造函数与析构函数(一)
- 吴恩达深度学习课程deeplearning.ai课程作业:Class 2 Week 1 3.Gradient Checking