• SpringBoot系列【SpringBoot集成定时任务框架Quartz】


    1.引入依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>

    2.新增配置

    server:
      port: 8082
      #优雅停机
      shutdown: graceful
    spring:
      application:
        name: fast-boot
      quartz:
        job-store-type: jdbc
      datasource:
    #    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    #    url: jdbc:p6spy:mysql://101.43.140.7:3307/home-finance?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&characterEncoding=utf-8
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://101.43.140.7:3307/home-finance?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&characterEncoding=utf-8
        username: root
        password: root
    #    druid:
    #      initial-size: 5                                                                 #初始化连接大小
    #      min-idle: 5                                                                     #最小连接池数量
    #      max-active: 20                                                                  #最大连接池数量
    #      max-wait: 60000                                                                 #获取连接时最大等待时间,单位毫秒
    #      time-between-eviction-runs-millis: 60000                                        #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    #      min-evictable-idle-time-millis: 300000                                          #配置一个连接在池中最小生存的时间,单位是毫秒
    #      validation-query: SELECT 1 FROM DUAL                                            #测试连接
    #      test-while-idle: true                                                           #申请连接的时候检测,建议配置为true,不影响性能,并且保证安全性
    #      test-on-borrow: false                                                           #获取连接时执行检测,建议关闭,影响性能
    #      test-on-return: false                                                           #归还连接时执行检测,建议关闭,影响性能
    #      pool-prepared-statements: false                                                 #是否开启PSCache,PSCache对支持游标的数据库性能提升巨大,oracle建议开启,mysql下建议关闭
    #      max-pool-prepared-statement-per-connection-size: 20                             #开启poolPreparedStatements后生效
    #      filters: stat,wall                                                              #配置扩展插件,常用的插件有=>stat:监控统计  wall:防御sql注入
    #      connection-properties: 'druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000' #通过connectProperties属性来打开mergeSql功能;慢SQL记录
    #
    #      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
    #      stat-view-servlet:
    #        enabled: true                                                                 #是否开启内置监控页面,默认值为 false
    #        url-pattern: '/druid/*'                                                       #StatViewServlet 的映射路径,即内置监控页面的访问地址
    #        reset-enable: true                                                            #是否启用重置按钮
    #        login-username: admin                                                         #内置监控页面的登录页用户名 username
    #        login-password: admin                                                         #内置监控页面的登录页密码 password
    #      # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
    #      web-stat-filter:
    #        enabled: true                                                                 #是否开启内置监控中的 Web-jdbc 关联监控的数据
    #        url-pattern: '/*'                                                             #匹配路径
    #        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'                     #排除路径
    #        session-stat-enable: true                                                     #是否监控session
    #      # Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置
    #      aop-patterns: com.fast.dao.*,com.fast.mapper                                               #Spring监控AOP切入点,如x.y.z.abc.*,配置多个英文逗号分隔
    #
    #      # 对配置已开启的 filters 即 stat(sql 监控)  wall(防火墙)
    #      filter:
    #        #配置StatFilter (SQL监控配置)
    #        stat:
    #          enabled: true                                                               #开启 SQL 监控
    #          slow-sql-millis: 1000                                                       #慢查询
    #          log-slow-sql: true                                                          #记录慢查询 SQL
    #        #配置WallFilter (防火墙配置)
    #        wall:
    #          enabled: true                                                               #开启防火墙
    #          config:
    #            update-allow: true                                                        #允许更新操作
    #            drop-table-allow: false                                                   #禁止删表操作
    #            insert-allow: true                                                       #允许插入操作
    #            delete-allow: true                                                        #删除数据操作
    knife4j:
      enable: true
    #  production: true
    
    #热部署模块
    #debug: false
    ##设置开启热部署
    #spring.devtools.restart.enabled: true
    ##页面不加载缓存,修改即时生效
    #spring.freemarker.cache: false
    ##设置修改文件后需要重启的目录
    #spring.devtools.restart.additional-paths: src/main/java
    #logging:
    #  com.fast.common.config: classpath:log4j2.xml
    mybatis-plus:
      mapper-locations: classpath:com/fast/mapper/*.xml
      type-aliases-package: com.fast.entity.pojo
    #  configuration:
    #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    3.编写接口

    package com.fast.controller;
    
    
    import cn.hutool.core.util.StrUtil;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.fast.common.result.common.Constant;
    import com.fast.common.result.common.R;
    import com.fast.entity.param.SysJobParam;
    import com.fast.entity.pojo.SysJob;
    import com.fast.entity.vo.SysJobVo;
    import com.fast.service.SysJobService;
    import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.*;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.Resource;
    import java.time.LocalDateTime;
    
    /**
     * (SysJob)表控制层
     *
     * @author hjw
     * @since 2022-03-30 17:47:52
     */
    @RestController
    @Api(tags = "定时任务管理")
    @Slf4j
    @RequestMapping("sysJob")
    public class SysJobController extends BaseController {
    
        @Resource
        private SysJobService sysJobService;
        @Resource
        private Scheduler scheduler;
    
        @ApiOperation(value = "条件分页查询")
        @PostMapping("/getAll")
        public R<Page<SysJobVo>> getAll(@RequestBody SysJobParam param) {
            return select(this.sysJobService.getAll(buildPage(param), param));
        }
    
        @ApiOperation(value = "根据id查")
        @GetMapping("/getDetailById/{id}")
        public R<SysJob> selectOne(@PathVariable("id") Long id) {
            return select(this.sysJobService.getById(id));
        }
    
        @ApiOperationSupport(ignoreParameters = {"sysJob.id", "sysJob.status"})
        @ApiOperation(value = "添加")
        @PostMapping("/add")
        public R<Boolean> insert(@RequestBody SysJob sysJob) {
            return add(this.sysJobService.save(sysJob));
        }
    
        @ApiOperation(value = "更新")
        @PutMapping("/update")
        public R<Boolean> update(@RequestBody SysJob sysJob) throws SchedulerException {
            //获取修改前的任务组名,停止触发器,再进行移除旧的任务
            SysJob oldSysJob = sysJobService.getById(sysJob.getId());
            if (StrUtil.isNotBlank(oldSysJob.getJobgroup())) {
                TriggerKey triggerKey = TriggerKey.triggerKey(oldSysJob.getName(), oldSysJob.getJobgroup());
                //停止触发器
                scheduler.pauseTrigger(triggerKey);
                //移除触发器
                scheduler.unscheduleJob(triggerKey);
                JobKey jobKey = new JobKey(oldSysJob.getName(), oldSysJob.getJobgroup());
                //删除任务
                scheduler.deleteJob(jobKey);
            }
            sysJob.setStatus(Constant.JOB_STATUS_STOP);
            sysJob.setUpdateTime(LocalDateTime.now());
            sysJob.setUpdateBy("管理员");
            return update(this.sysJobService.updateById(sysJob));
        }
    
        @ApiOperation(value = "删除定时任务")
        @DeleteMapping("/del/{id}")
        public R<Boolean> delete(@PathVariable("id") Long id) {
            SysJob sysJob = sysJobService.getById(id);
            if (sysJob == null) {
                return R.fail("要删除的任务不存在,请检查id");
            }
    
            TriggerKey triggerKey = TriggerKey.triggerKey(sysJob.getName(), sysJob.getJobgroup());
            try {
                //停止触发器
                scheduler.pauseTrigger(triggerKey);
                //移除触发器
                scheduler.unscheduleJob(triggerKey);
                //删除任务
                scheduler.deleteJob(JobKey.jobKey(sysJob.getName(), sysJob.getJobgroup()));
            } catch (Exception e) {
                return R.fail(e.getMessage());
            }
    
            sysJob.setDel(Constant.DEL_DELETED);
            return delete(sysJobService.updateById(sysJob));
    
        }
    
        @ApiOperation(value = "启动定时任务")
        @PostMapping("/start")
        public R<Boolean> start(Long id) throws Exception {
            SysJob sysJob = sysJobService.getById(id);
            if (sysJob.getStatus().equals(Constant.JOB_STATUS_RUN)) {
                return R.fail("任务正在执行");
            } else if (sysJob.getStatus().equals(Constant.JOB_STATUS_STOP)) {
                return R.fail("任务处于停止状态,只能继续执行");
            }
            //启动任务
            addJob(sysJob);
            sysJob.setStatus(Constant.JOB_STATUS_RUN);
            sysJobService.updateById(sysJob);
            return R.success("启动成功");
        }
    
        public void addJob(SysJob sysJob) throws Exception {
            Class cls = Class.forName(sysJob.getInvoketarget());
            cls.newInstance();
    
            //构建JobDetail
            JobDetail jobDetail = JobBuilder.newJob(cls)
                    .withIdentity(sysJob.getName(), sysJob.getJobgroup())
                    .withDescription(sysJob.getRemark())
                    .build();
    
            //执行时间
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(sysJob.getCronexpression());
    
            //构建trigger,触发器
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger" + sysJob.getName(), sysJob.getJobgroup())
                    .withDescription(sysJob.getRemark())
                    .startNow()
                    .withSchedule(cronScheduleBuilder)
                    .build();
    
            //交由调度器调度
            scheduler.scheduleJob(jobDetail, trigger);
        }
    
        @ApiOperation(value = "停止任务")
        @PostMapping("/pause")
        public R<Boolean> pause(Long id) throws Exception {
            SysJob sysJob = sysJobService.getById(id);
            if (sysJob.getStatus().equals(Constant.JOB_STATUS_RUN)) {
                JobKey key = new JobKey(sysJob.getName(), sysJob.getJobgroup());
                scheduler.pauseJob(key);
                sysJob.setStatus(Constant.JOB_STATUS_STOP);
            } else if (sysJob.getStatus().equals(Constant.JOB_STATUS_STOP)) {
                return R.fail("任务已处于停止状态");
            } else if (sysJob.getStatus().equals(Constant.JOB_STATUS_INIT)) {
                return R.fail("任务还未执行");
            }
            sysJobService.updateById(sysJob);
            return R.success("停止成功");
        }
    
        @ApiOperation(value = "继续任务")
        @PostMapping("/keep")
        public R<Boolean> keep(Long id) throws Exception {
            SysJob sysJob = sysJobService.getById(id);
            if (sysJob.getStatus().equals(Constant.JOB_STATUS_STOP)) {
                JobKey key = new JobKey(sysJob.getName(), sysJob.getJobgroup());
                scheduler.resumeJob(key);
                sysJob.setStatus(Constant.JOB_STATUS_STOP);
            } else if (sysJob.getStatus().equals(Constant.JOB_STATUS_RUN)) {
                return R.fail("任务正在运行");
            } else if (sysJob.getStatus().equals(Constant.JOB_STATUS_INIT)) {
                return R.fail("任务还未执行");
            }
            sysJobService.updateById(sysJob);
            return R.success("停止成功");
        }
    
        @ApiOperation(value = "手动执行一次", tags = "不管任务是处于运行状态还是暂停,都会手动执行一次,未运行的任务,无法执行")
        @PostMapping("/triggerJob")
        public R<Boolean> triggerJob(@RequestBody SysJob sysJob) throws Exception {
            JobKey key = new JobKey(sysJob.getName(), sysJob.getJobgroup());
            scheduler.triggerJob(key);
            return R.success("手动执行一次成功");
        }
    }

     4.创建表

    create table sys_job
    (
        id             bigint       not null comment '任务id'
            primary key,
        name           varchar(256) null comment '任务名称',
        invokeTarget   varchar(256) null comment '调用目标字符串',
        jobGroup       varchar(100) null comment '任务组名',
        cronExpression varchar(100) null comment '执行表达式',
        misfirPolicy   varchar(1)   null comment '计划策略(0-默认,1-立即执行,2-触发一次执行,3-不触发立即执行)',
        concurrent     varchar(1)   null comment '是否并发执行(0-允许,1-禁止)',
        status         varchar(1)   null comment '状态(0正常,1暂停)',
        create_time    datetime     null comment '创建时间',
        create_by      varchar(32)  null comment '创建人',
        update_time    datetime     null comment '更新时间',
        update_by      varchar(32)  null comment '更新人',
        del            varchar(1)   null comment '删除标志',
        remark         varchar(256) null comment '备注'
    );
  • 相关阅读:
    查看unity打来的包在手机上面查看日志
    Unity 打包出来动态加载图片丢失问题
    嵌套列表拖拽事件冲突问题
    游戏中实现鼠标拖尾效果
    2048
    面试知识点积累
    ARM处理器架构理论知识
    計算機網絡知識點總結:
    collection
    demo002.链表操作
  • 原文地址:https://www.cnblogs.com/hujunwei/p/16104080.html
Copyright © 2020-2023  润新知