QiYuAdmin-Quartz定时器动态启停服务(SpringBoot项目实战)

简介

  • Quartz介绍
  • 成果展示
  • QiYuAdmin集Quartz
  • Quartz的API封装和数据库设计
  • 页面和功能开发

Quartz介绍

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。

成果展示

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

QiYuAdmin集成Quartz

  • 父pom文件(控制继承)
    <dependencyManagement>
        <dependency>
               <groupId>org.quartz-scheduler</groupId>
               <artifactId>quartz</artifactId>
               <version>${quartz.version}</version>
        </dependency>
     </dependencyManagement>
  • 子pom文件(引用)
    <dependency>
         <groupId>org.quartz-scheduler</groupId>
         <artifactId>quartz</artifactId>
    </dependency>

Quartz的API封装和数据库设计

这里没有用SpringBoot集成Quartz的javaconfig模式配置,网上也有:SpringBoot集成Quartz
这里我引用了之前公司老项目的做法,单节点不是集群,配置的简单了点。后续研究研究集群环境的Quartz。现在的做法是先在数据库里面创建表

这里写图片描述

然后将定时器给启动起来,启动定时器的地方可以放在服务器启动的时候,我们这里就先放在当点击菜单《定时器》的时候触发启动定时器。当点击菜单《定时器》的时候触发的步骤是:
1. 开启定时器
2. 从数据库里面查询所有任务列表
3. 将这些任务列表放在定时器(Schedule)里面
4. 根据数据库存储的任务状态来进行启停服务

 SchedulerManager.start();//开启定时器
        //注册所有任务到scheduler里面,并根据scheduler的状态来开启任务
        List<SystemScheduler> 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();
        }
    }
}();

简介

收工。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Spring Boot中,可以使用Quartz框架来实现定时任务。下面是一个简单的配置示例: 1. 添加依赖 在pom.xml中添加Quartz依赖: ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency> ``` 2. 配置Job和Trigger 在程序中定义一个Job,示例代码如下: ```java @Component public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 定时任务执行的逻辑 } } ``` 然后定义一个Trigger,示例代码如下: ```java @Component public class MyTrigger { @Bean public JobDetail jobDetail() { return JobBuilder.newJob(MyJob.class) .withIdentity("myJob") .storeDurably() .build(); } @Bean public Trigger trigger() { return TriggerBuilder.newTrigger() .forJob(jobDetail()) .withIdentity("myTrigger") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // 每5秒执行一次 .build(); } } ``` 3. 配置Scheduler 创建一个SchedulerFactoryBean,配置其中的Scheduler实例,示例代码如下: ```java @Configuration public class QuartzConfig { @Autowired private MyTrigger myTrigger; @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setTriggers(myTrigger.trigger()); return schedulerFactoryBean; } } ``` 4. 动应用程序 在应用程序动时,Scheduler会自动动,定时任务也会随之开始执行。 注意事项: - 如果需要并发执行Job,可以在Job类上添加注解@DisallowConcurrentExecution。 - 如果需要持久化Job信息,可以配置JobStore,例如使用JDBCJobStore将Job信息存储到数据库中。 - 如果需要动态创建和管理Job和Trigger,可以使用JobDetailFactory和TriggerFactory来创建Job和Trigger,并使用Scheduler来管理它们。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山竹之七语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值