Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>${quartz.version}version>
dependency>
dependencyManagement>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
dependency>
这里没有用SpringBoot集成Quartz的javaconfig模式配置,网上也有:SpringBoot集成Quartz
这里我引用了之前公司老项目的做法,单节点不是集群,配置的简单了点。后续研究研究集群环境的Quartz。现在的做法是先在数据库里面创建表
然后将定时器给启动起来,启动定时器的地方可以放在服务器启动的时候,我们这里就先放在当点击菜单《定时器》的时候触发启动定时器。当点击菜单《定时器》的时候触发的步骤是:
1. 开启定时器
2. 从数据库里面查询所有任务列表
3. 将这些任务列表放在定时器(Schedule)里面
4. 根据数据库存储的任务状态来进行启停服务
SchedulerManager.start();//开启定时器
//注册所有任务到scheduler里面,并根据scheduler的状态来开启任务
List schedulerList = schedulerMapper.selectAll();
if(HelpUtils.isNotEmpty(schedulerList)){
for(SystemScheduler scheduler :schedulerList){
SchedulerManager.addScheduler(scheduler);//将任务放在定时器里面并根据状态启停服务
}
}
pageNo = pageNo == null?1:pageNo;
pageSize = pageSize == null?10:pageSize;
PageHelper.startPage(pageNo,pageSize); //startPage是告诉拦截器说我要开始分页了。分页参数是这两个。
return BeanUtil.toPagedResult(schedulerMapper.selectByCondition(systemScheduler));
以上代码开启定时器方法和添加一个任务的方法封装到了SchedulerManager里面了。添加完任务到scheduler中之后在根据数据库查询出来的isStart进行启停服务。
开启服务代码:
public static void start(){
quartzManager.startJobs();
}
public void startJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
if (!sched.isStarted()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
增加任务到定时器里面并根据数据库的状态来启停服务器代码:
public static void addScheduler(SystemScheduler scheduler) {
addOrModify(scheduler);
}
private static void addOrModify(SystemScheduler scheduler) {
// job类处理
Class extends Job> jobclass = verify(scheduler);
// 添加到调度器
if (!HelpUtils.isEmpty(jobclass)) {
if (quartzManager.isExist(getJobName(scheduler))) {// 存在
quartzManager.modifyJobTime(getJobName(scheduler), scheduler.getCron(),
quartzManager.getJobDataMap(scheduler.getJobParams()));
} else {// 不存在
quartzManager.addJob(getJobName(scheduler), jobclass, scheduler.getCron(),
quartzManager.getJobDataMap(scheduler.getJobParams()));
}
pauseJob(scheduler);//根据状态启停服务
}
}
public static void pauseJob(SystemScheduler scheduler) {
String jobName = getJobName(scheduler);
if (scheduler.getIsStart().equalsIgnoreCase("1")) {// 开启一个任务
quartzManager.resumeJob(jobName);
} else if (scheduler.getIsStart().equalsIgnoreCase("0")) {// 暂停一个任务
quartzManager.pauseJob(jobName);
}
}
QuartzManager、SchedulerManager两个文件放在云盘上。下载
不知不觉中,也有了几个模块了(用户、部门、会话、菜单、定时器)
主界面代码如下:
scheduler.js代码如下,基本的套路和之前的用户一样,看下应该就明白了。
//@ sourceURL=scheduler.js
/**
* 定时器模块js:包括主界面、修改定时器界面
*/
var QiYuScheduler = function () {
//定时任务主页面属性开始
var schedulerTableId = "schedulerTable";
var $schedulerTable=$("#schedulerTable");
var tableAjaxUrl="scheduler/page/list";
var schedulerTableTableColum=[{checkbox: true}
,{title: 'id',field: 'id',align: 'center',valign: 'middle',visible:false}
,{title: '任务名称',field: 'jobName',align: 'center',valign: 'middle'}
,{title: '任务状态',field: 'isStart',align: 'center',valign: 'middle'}
,{title: 'cron表达式',field: 'cron',align: 'center',valign: 'middle'}
,{title: '创建人',field: 'createBy',align: 'center',valign: 'middle'}
,{title: '创建时间',field: 'createDate',align: 'center',valign: 'middle'}
,{title: '修改人',field: 'updateBy',align: 'center',formatter:function (value,row,index){
if(null==value || ""==value){
return "-";
}
return value;
}}
,{title: '修改日期',field: 'gender',align: 'center',valign: 'middle',formatter:function (value,row,index) {
if(null==value || ""==value){
return "-";
}
return new Date(value).format("yyyy-MM-dd hh:mm:ss");
}}
];
var $startSchedulers=$("#startSchedulers");
var $stopSchedulers=$("#stopSchedulers");
var $updateSchedulerView=$("#updateSchedulerView");
//定时任务主页面属性结束
//定时任务修改页面属性
var $updateSchedulerForm =$("#schedulerUpdateForm");
var updateSchedulerForm ="schedulerUpdateForm";
var $updateSchedulerBtn = $("#updateSchedulerBtn");
var updateAjaxUrl = QiYuComponents.getContextPath()+"/scheduler";
/**
* 定时器主页面初始化定时器表格数据
*/
var initTable=function () {
QiYuComponents.initBootStrapTable($schedulerTable,tableAjaxUrl,schedulerTableTableColum);
}
/**
* 定时器主页面按钮绑定事件:启动、修改、停止
*/
var schedulerMainEventHandler=function () {
//绑定修改定时任务弹出页面的按钮事件
$updateSchedulerView.on("click",function () {
var rows = QiYuComponents.getTableSelections($schedulerTable);
if(rows.length==0){
QiYuComponents.bootstrapSweetAlert("","请选择一个定时任务","error");
return;
}
if(rows.length>=2){
QiYuComponents.bootstrapSweetAlert("","不能选择多个定时任务","error");
return;
}
//查看的基定时器本信息
QiYuComponents.layerOpen("配置定时器",'900px','450px',"scheduler/update/view/"+rows[0].id);
});
//绑定停止定时器事件---------可以和下面的事件绑定合成一个,后续优化
$stopSchedulers.on("click",function () {
var rows = QiYuComponents.getTableSelections($schedulerTable);
if(rows.length==0){
QiYuComponents.bootstrapSweetAlert("","请选择一个定时器","error");
return false;
}
if(rows.length==1){
var isStart = rows[0].isStart;
if(isStart=="关闭"){
QiYuComponents.bootstrapSweetAlert("","此任务已经关闭","error");
return false;
}
}
if(rows.length > 1){
var isStartDataAry=[];
$.each(rows, function(i, obj) {
isStartDataAry.push(obj.isStart);
});
var flag = $.inArray("开启", isStartDataAry);
if(flag==-1){
QiYuComponents.bootstrapSweetAlert("","所选择的任务已经全部关闭了","error");
return false;
}
}
var idDataAry=[];
$.each(rows, function(i, obj) {
if(obj.isStart=="开启"){
idDataAry.push(obj.id);
}
});
ajaxChangeJobStatus(idDataAry,"scheduler/status/0");
});
//绑定开启定时器事件
$startSchedulers.on("click",function () {
var rows = QiYuComponents.getTableSelections($schedulerTable);
if(rows.length==0){
QiYuComponents.bootstrapSweetAlert("","请选择一个定时器","error");
return false;
}
if(rows.length==1){
var isStart = rows[0].isStart;
if(isStart=="开启"){
QiYuComponents.bootstrapSweetAlert("","此任务已经开启","error");
return false;
}
}
if(rows.length > 1){
var isStartDataAry=[];
$.each(rows, function(i, obj) {
isStartDataAry.push(obj.isStart);
});
var flag = $.inArray("关闭", isStartDataAry);
if(flag==-1){
QiYuComponents.bootstrapSweetAlert("","所选择的任务已经全部开启了","error");
return;
}
}
var idDataAry=[];
$.each(rows, function(i, obj) {
if(obj.isStart=="关闭"){
idDataAry.push(obj.id);
}
});
ajaxChangeJobStatus(idDataAry,"scheduler/status/1");
});
}
var ajaxChangeJobStatus = function(idDataAry,url){
$.ajax({
type:"POST",
url:url,
contentType: "application/json",//加入contentType,后端需要用requestBody接受参数,此时的参数不在request里面了
data: JSON.stringify(idDataAry),
dataType: "json",
success:function(responseJson){
if(responseJson.success==true){//返回true
QiYuComponents.bootstrapSweetAlert("",responseJson.msg,"success");
QiYuComponents.refreshTable($schedulerTable);
}
if(responseJson.success==false){//返回false
QiYuComponents.bootstrapSweetAlert("",responseJson.msg,"error");
}
},
beforeSend:function(XMLHttpRequest){
//请求之前方法增强处理 ,显示遮罩层
App.blockUI({target: '.page-content',animate: true});
},
complete:function(XMLHttpRequest, textStatus){
//请求结束方法增强处理 ,隐藏遮罩层
App.unblockUI('.page-content');
},
error:function (XMLHttpRequest, textStatus) {
QiYuComponents.bootstrapSweetAlert("","请联系管理员!","error");
}
});
}
/**
* 定时任务修改页面验证表单
*/
var initUserUpdateBootStrapValidate = function () {
$updateSchedulerForm.bootstrapValidator({
// trigger: 'blur',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
jobName: {
validators: {
notEmpty: {
message: '任务名称不能为空'
}
}
},
jobClass:{
validators: {
notEmpty: {
message: '类不能为空'
}
}
},
cron:{
validators: {
notEmpty: {
message: 'cron表达式不能为空'
}
}
}
}
}).on("success.form.bv",function(e){
QiYuComponents.qiYuAjaxFormSumbitTable(updateAjaxUrl,updateSchedulerForm,schedulerTableId);
});
}
var schedulerUpdateEnventHandler = function () {
$updateSchedulerBtn.on("click",function () {
$updateSchedulerForm.submit();
});
}
return{
//初始化主界面
initSchedulerMain:function () {
initTable();
schedulerMainEventHandler();
},
initSchedulerUpdate:function () {
initUserUpdateBootStrapValidate();
schedulerUpdateEnventHandler();
}
}
}();
收工。