沙钢智慧能源系统后端代码
liriming
2024-10-14 516ef4b0df8c26a3088e113e39d8198f161d4ea4
定时任务
已修改2个文件
已添加22个文件
1180 ■■■■■ 文件已修改
shasteel-biz/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/config/ScheduleConfig.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobController.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobLogController.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/package-info.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobDao.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobLogDao.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobDTO.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobLogDTO.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobEntity.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobLogEntity.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/init/JobCommandLineRunner.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobLogService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobService.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobLogServiceImpl.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobServiceImpl.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/ITask.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/TestTask.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleJob.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleUtils.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/vo/ScheduleJobReqVO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/resources/application.yaml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/resources/mapper/job/ScheduleJobDao.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/src/main/resources/mapper/job/ScheduleJobLogDao.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
shasteel-biz/pom.xml
@@ -131,6 +131,13 @@
            <artifactId>tencentcloud-sdk-java-sms</artifactId> <!-- 短信(腾讯云) -->
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
        </dependency>
    </dependencies>
    <build>
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/config/ScheduleConfig.java
对比新文件
@@ -0,0 +1,58 @@
package com.iailab.module.shasteel.job.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
/**
 * 定时任务配置
 *
 * @author Mark sunlightcs@gmail.com
 */
@Configuration
public class ScheduleConfig {
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);
        //quartz参数
        Properties prop = new Properties();
        prop.put("org.quartz.scheduler.instanceName", "IailabDataScheduler");
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        //线程池配置
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "20");
        prop.put("org.quartz.threadPool.threadPriority", "5");
        //JobStore配置
        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
        //集群配置
        prop.put("org.quartz.jobStore.isClustered", "true");
        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
        //PostgreSQL数据库,需要打开此注释
        //prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
        factory.setQuartzProperties(prop);
        factory.setSchedulerName("IailabDataScheduler");
        //延时启动
        factory.setStartupDelay(30);
        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
        //可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        factory.setOverwriteExistingJobs(true);
        //设置自动启动,默认为true
        factory.setAutoStartup(true);
        return factory;
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobController.java
对比新文件
@@ -0,0 +1,127 @@
package com.iailab.module.shasteel.job.controller.admin;
import com.iailab.framework.common.constant.Constant;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.validation.ValidationUtils;
import com.iailab.framework.common.validation.group.AddGroup;
import com.iailab.framework.common.validation.group.DefaultGroup;
import com.iailab.framework.common.validation.group.UpdateGroup;
import com.iailab.framework.tenant.core.context.TenantContextHolder;
import com.iailab.module.shasteel.job.dto.ScheduleJobDTO;
import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
import com.iailab.module.shasteel.job.service.ScheduleJobService;
import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import static com.iailab.framework.common.pojo.CommonResult.success;
/**
 * 定时任务
 *
 * @author Mark sunlightcs@gmail.com
 */
@RestController
@RequestMapping("/job/schedule")
@Tag(name = "定时任务")
public class ScheduleJobController {
    @Resource
    private ScheduleJobService scheduleJobService;
    @GetMapping("page")
    @Operation(summary = "分页")
    @Parameters({
        @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true) ,
        @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true) ,
        @Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
        @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)") ,
        @Parameter(name = "beanName", description = "beanName")
    })
    @PreAuthorize("@ss.hasPermission('data:schedule:query')")
    public CommonResult<PageResult<ScheduleJobDTO>> page(@Validated ScheduleJobReqVO reqVO){
        reqVO.setTenantId(TenantContextHolder.getTenantId());
        PageResult<ScheduleJobEntity> page = scheduleJobService.page(reqVO);
        return success(BeanUtils.toBean(page, ScheduleJobDTO.class));
    }
    @GetMapping("info")
    @Operation(summary = "信息")
    @PreAuthorize("@ss.hasPermission('data:schedule:query')")
    public CommonResult<ScheduleJobDTO> info(@RequestParam("id") Long id){
        ScheduleJobDTO schedule = scheduleJobService.get(id);
        return new CommonResult<ScheduleJobDTO>().setData(schedule);
    }
    @PostMapping("/create")
    @Operation(summary = "保存")
    @PreAuthorize("@ss.hasPermission('data:schedule:create')")
    public CommonResult save(@RequestBody ScheduleJobDTO dto){
        ValidationUtils.validate(dto, AddGroup.class, DefaultGroup.class);
        scheduleJobService.save(dto);
        return new CommonResult();
    }
    @PutMapping("/update")
    @Operation(summary = "修改")
    @PreAuthorize("@ss.hasPermission('data:schedule:update')")
    public CommonResult update(@RequestBody ScheduleJobDTO dto){
        ValidationUtils.validate(dto, UpdateGroup.class, DefaultGroup.class);
        scheduleJobService.update(dto);
        return new CommonResult();
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除")
    @PreAuthorize("@ss.hasPermission('data:schedule:delete')")
    public CommonResult delete(@RequestParam("id") Long id){
        scheduleJobService.deleteBatch(id);
        return new CommonResult();
    }
    @PutMapping("/run")
    @Operation(summary = "立即执行")
    public CommonResult run(@RequestParam("id") Long id){
        Long[] ids = new Long[1];
        ids[0] = id;
        scheduleJobService.run(ids);
        return new CommonResult();
    }
    @PutMapping("/pause")
    @Operation(summary = "暂停")
    public CommonResult pause(@RequestParam("id") Long id){
        Long[] ids = new Long[1];
        ids[0] = id;
        scheduleJobService.pause(ids);
        return new CommonResult();
    }
    @PutMapping("/resume")
    @Operation(summary = "恢复")
    public CommonResult resume(@RequestParam("id") Long id){
        Long[] ids = new Long[1];
        ids[0] = id;
        scheduleJobService.resume(ids);
        return new CommonResult();
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobLogController.java
对比新文件
@@ -0,0 +1,62 @@
/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */
package com.iailab.module.shasteel.job.controller.admin;
import com.iailab.framework.common.constant.Constant;
import com.iailab.framework.common.page.PageData;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
import com.iailab.module.shasteel.job.service.ScheduleJobLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
/**
 * 定时任务日志
 *
 * @author Mark sunlightcs@gmail.com
 */
@RestController
@RequestMapping("/sys/scheduleLog")
@Tag(name = "定时任务日志")
public class ScheduleJobLogController {
    @Resource
    private ScheduleJobLogService scheduleJobLogService;
    @GetMapping("page")
    @Operation(summary = "分页")
    @Parameters({
        @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true) ,
        @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true) ,
        @Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
        @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)") ,
        @Parameter(name = "jobId", description = "jobId")
    })
    @PreAuthorize("@ss.hasPermission('sys:schedule:log')")
    public CommonResult<PageData<ScheduleJobLogDTO>> page(@RequestParam Map<String, Object> params){
        PageData<ScheduleJobLogDTO> page = scheduleJobLogService.page(params);
        return new CommonResult<PageData<ScheduleJobLogDTO>>().setData(page);
    }
    @GetMapping("{id}")
    @Operation(summary = "信息")
    @PreAuthorize("@ss.hasPermission('sys:schedule:log')")
    public CommonResult<ScheduleJobLogDTO> info(@PathVariable("id") Long id){
        ScheduleJobLogDTO log = scheduleJobLogService.get(id);
        return new CommonResult<ScheduleJobLogDTO>().setData(log);
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/package-info.java
对比新文件
@@ -0,0 +1 @@
package com.iailab.module.shasteel.job.controller;
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobDao.java
对比新文件
@@ -0,0 +1,34 @@
package com.iailab.module.shasteel.job.dao;
import com.baomidou.dynamic.datasource.annotation.Master;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Map;
/**
 * 定时任务
 *
 * @author Mark sunlightcs@gmail.com
 */
@Master
@Mapper
public interface ScheduleJobDao extends BaseMapperX<ScheduleJobEntity> {
    default PageResult<ScheduleJobEntity> selectPage(ScheduleJobReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<ScheduleJobEntity>()
                .likeIfPresent(ScheduleJobEntity::getBeanName, reqVO.getBeanName())
                .eqIfPresent(ScheduleJobEntity::getTenantId, reqVO.getTenantId())
                .orderByDesc(ScheduleJobEntity::getCreateDate));
    }
    /**
     * 批量更新状态
     */
    int updateBatch(Map<String, Object> map);
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobLogDao.java
对比新文件
@@ -0,0 +1,17 @@
package com.iailab.module.shasteel.job.dao;
import com.baomidou.dynamic.datasource.annotation.Master;
import com.iailab.framework.common.dao.BaseDao;
import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
import org.apache.ibatis.annotations.Mapper;
/**
 * 定时任务日志
 *
 * @author Mark sunlightcs@gmail.com
 */
@Master
@Mapper
public interface ScheduleJobLogDao extends BaseDao<ScheduleJobLogEntity> {
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobDTO.java
对比新文件
@@ -0,0 +1,62 @@
/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */
package com.iailab.module.shasteel.job.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.iailab.framework.common.validation.group.AddGroup;
import com.iailab.framework.common.validation.group.DefaultGroup;
import com.iailab.framework.common.validation.group.UpdateGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.io.Serializable;
import java.util.Date;
/**
 * 定时任务
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0
 */
@Data
@Tag(name = "定时任务")
public class ScheduleJobDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "id")
    @Null(message="{id.null}", groups = AddGroup.class)
    @NotNull(message="{id.require}", groups = UpdateGroup.class)
    private Long id;
    @Schema(description = "spring bean名称")
    @NotBlank(message = "{schedule.bean.require}", groups = DefaultGroup.class)
    private String beanName;
    @Schema(description = "参数")
    private String params;
    @Schema(description = "cron表达式")
    @NotBlank(message = "{schedule.cron.require}", groups = DefaultGroup.class)
    private String cronExpression;
    @Schema(description = "任务状态  0:暂停  1:正常")
    private Integer status;
    @Schema(description = "备注")
    private String remark;
    @Schema(description = "创建时间")
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private Date createDate;
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobLogDTO.java
对比新文件
@@ -0,0 +1,53 @@
/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */
package com.iailab.module.shasteel.job.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * 定时任务日志
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0
 */
@Data
@Tag(name = "定时任务日志")
public class ScheduleJobLogDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "id")
    private Long id;
    @Schema(description = "任务id")
    private Long jobId;
    @Schema(description = "spring bean名称")
    private String beanName;
    @Schema(description = "参数")
    private String params;
    @Schema(description = "任务状态    0:失败    1:成功")
    private Integer status;
    @Schema(description = "失败信息")
    private String error;
    @Schema(description = "耗时(单位:毫秒)")
    private Integer times;
    @Schema(description = "创建时间")
    private Date createDate;
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobEntity.java
对比新文件
@@ -0,0 +1,58 @@
package com.iailab.module.shasteel.job.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.iailab.framework.common.entity.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
 * 定时任务
 *
 * @author Mark sunlightcs@gmail.com
 */
@Data
@EqualsAndHashCode(callSuper=false)
@TableName("schedule_job")
public class ScheduleJobEntity extends BaseEntity {
    private static final long serialVersionUID = 1L;
    /**
     * spring bean名称
     */
    private String beanName;
    /**
     * 参数
     */
    private String params;
    /**
     * cron表达式
     */
    private String cronExpression;
    /**
     * 任务状态  0:暂停  1:正常
     */
    private Integer status;
    /**
     * 备注
     */
    private String remark;
    /**
     * 更新者
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updater;
    /**
     * 更新时间
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateDate;
    /**
     * 多租户编号
     */
    private Long tenantId;
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobLogEntity.java
对比新文件
@@ -0,0 +1,59 @@
package com.iailab.module.shasteel.job.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * 定时任务日志
 *
 * @author Mark sunlightcs@gmail.com
 */
@Data
@TableName("schedule_job_log")
public class ScheduleJobLogEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @TableId
    private Long id;
    /**
     * 任务id
     */
    private Long jobId;
    /**
     * spring bean名称
     */
    private String beanName;
    /**
     * 参数
     */
    private String params;
    /**
     * 任务状态    0:失败    1:成功
     */
    private Integer status;
    /**
     * 失败信息
     */
    private String error;
    /**
     * 耗时(单位:毫秒)
     */
    private Integer times;
    /**
     * 创建时间
     */
    private Date createDate;
    /**
     * 多租户编号
     */
    private Long tenantId;
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/init/JobCommandLineRunner.java
对比新文件
@@ -0,0 +1,38 @@
package com.iailab.module.shasteel.job.init;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iailab.module.shasteel.job.dao.ScheduleJobDao;
import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
import com.iailab.module.shasteel.job.utils.ScheduleUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
 * 初始化定时任务数据
 */
@Component
public class JobCommandLineRunner implements CommandLineRunner {
    @Resource
    private Scheduler scheduler;
    @Resource
    private ScheduleJobDao scheduleJobDao;
    @Override
    public void run(String... args) {
        List<ScheduleJobEntity> scheduleJobList = scheduleJobDao.selectList(new QueryWrapper<>());
        for(ScheduleJobEntity scheduleJob : scheduleJobList){
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
            //如果不存在,则创建
            if(cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            }else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobLogService.java
对比新文件
@@ -0,0 +1,29 @@
/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */
package com.iailab.module.shasteel.job.service;
import com.iailab.framework.common.page.PageData;
import com.iailab.framework.common.service.BaseService;
import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
import java.util.Map;
/**
 * 定时任务日志
 *
 * @author Mark sunlightcs@gmail.com
 */
public interface ScheduleJobLogService extends BaseService<ScheduleJobLogEntity> {
    PageData<ScheduleJobLogDTO> page(Map<String, Object> params);
    ScheduleJobLogDTO get(Long id);
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobService.java
对比新文件
@@ -0,0 +1,55 @@
package com.iailab.module.shasteel.job.service;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.service.BaseService;
import com.iailab.module.shasteel.job.dto.ScheduleJobDTO;
import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
/**
 * 定时任务
 *
 * @author Mark sunlightcs@gmail.com
 */
public interface ScheduleJobService{
    PageResult<ScheduleJobEntity> page(ScheduleJobReqVO reqVO);
    ScheduleJobDTO get(Long id);
    /**
     * 保存定时任务
     */
    void save(ScheduleJobDTO dto);
    /**
     * 更新定时任务
     */
    void update(ScheduleJobDTO dto);
    /**
     * 批量删除定时任务
     */
    void deleteBatch(Long id);
    /**
     * 批量更新定时任务状态
     */
    int updateBatch(Long[] ids, int status);
    /**
     * 立即执行
     */
    void run(Long[] ids);
    /**
     * 暂停运行
     */
    void pause(Long[] ids);
    /**
     * 恢复运行
     */
    void resume(Long[] ids);
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobLogServiceImpl.java
对比新文件
@@ -0,0 +1,54 @@
/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */
package com.iailab.module.shasteel.job.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.iailab.framework.common.constant.Constant;
import com.iailab.framework.common.page.PageData;
import com.iailab.framework.common.service.impl.BaseServiceImpl;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.module.shasteel.job.dao.ScheduleJobLogDao;
import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
import com.iailab.module.shasteel.job.service.ScheduleJobLogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class ScheduleJobLogServiceImpl extends BaseServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
    @Override
    public PageData<ScheduleJobLogDTO> page(Map<String, Object> params) {
        IPage<ScheduleJobLogEntity> page = baseDao.selectPage(
            getPage(params, Constant.CREATE_DATE, false),
            getWrapper(params)
        );
        return getPageData(page, ScheduleJobLogDTO.class);
    }
    private QueryWrapper<ScheduleJobLogEntity> getWrapper(Map<String, Object> params){
        String jobId = (String)params.get("jobId");
        QueryWrapper<ScheduleJobLogEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(jobId), "job_id", jobId);
        return wrapper;
    }
    @Override
    public ScheduleJobLogDTO get(Long id) {
        ScheduleJobLogEntity entity = baseDao.selectById(id);
        return ConvertUtils.sourceToTarget(entity, ScheduleJobLogDTO.class);
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobServiceImpl.java
对比新文件
@@ -0,0 +1,128 @@
package com.iailab.module.shasteel.job.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.constant.Constant;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.service.impl.BaseServiceImpl;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
import com.iailab.framework.tenant.core.context.TenantContextHolder;
import com.iailab.module.shasteel.job.dao.ScheduleJobDao;
import com.iailab.module.shasteel.job.dto.ScheduleJobDTO;
import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
import com.iailab.module.shasteel.job.service.ScheduleJobService;
import com.iailab.module.shasteel.job.utils.ScheduleUtils;
import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Scheduler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Service
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
    @Resource
    private Scheduler scheduler;
    @Resource
    private ScheduleJobDao scheduleJobDao;
    @Override
    public PageResult<ScheduleJobEntity> page(ScheduleJobReqVO reqVO) {
        return scheduleJobDao.selectPage(reqVO);
    }
    @Override
    public ScheduleJobDTO get(Long id) {
        ScheduleJobEntity entity = scheduleJobDao.selectById(id);
        return ConvertUtils.sourceToTarget(entity, ScheduleJobDTO.class);
    }
    private QueryWrapper<ScheduleJobEntity> getWrapper(Map<String, Object> params){
        String beanName = (String)params.get("beanName");
        QueryWrapper<ScheduleJobEntity> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(beanName), "bean_name", beanName);
        return wrapper;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(ScheduleJobDTO dto) {
        Long tenantId = TenantContextHolder.getRequiredTenantId();
        ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
        entity.setId(System.currentTimeMillis());
        entity.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
        entity.setTenantId(tenantId);
        entity.setCreator(SecurityFrameworkUtils.getLoginUser().getId());
        entity.setCreateDate(new Date());
        scheduleJobDao.insert(entity);
        ScheduleUtils.createScheduleJob(scheduler, entity);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ScheduleJobDTO dto) {
        Long tenantId = TenantContextHolder.getRequiredTenantId();
        ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
        entity.setUpdateDate(new Date());
        entity.setUpdater(SecurityFrameworkUtils.getLoginUser().getId());
        entity.setTenantId(tenantId);
        ScheduleUtils.updateScheduleJob(scheduler, entity);
        this.updateById(entity);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(Long id) {
        ScheduleUtils.deleteScheduleJob(scheduler, id);
        scheduleJobDao.deleteById(id);
    }
    @Override
    public int updateBatch(Long[] ids, int status){
        Map<String, Object> map = new HashMap<>(2);
        map.put("ids", ids);
        map.put("status", status);
        return scheduleJobDao.updateBatch(map);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void run(Long[] ids) {
        for(Long id : ids){
            ScheduleUtils.run(scheduler, scheduleJobDao.selectById(id));
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pause(Long[] ids) {
        for(Long id : ids){
            ScheduleUtils.pauseJob(scheduler, id);
        }
        updateBatch(ids, Constant.ScheduleStatus.PAUSE.getValue());
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resume(Long[] ids) {
        for(Long id : ids){
            ScheduleUtils.resumeJob(scheduler, id);
        }
        updateBatch(ids, Constant.ScheduleStatus.NORMAL.getValue());
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/ITask.java
对比新文件
@@ -0,0 +1,25 @@
/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有,侵权必究!
 */
package com.iailab.module.shasteel.job.task;
/**
 * 定时任务接口,所有定时任务都要实现该接口
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0
 */
public interface ITask {
    /**
     * 执行定时任务接口
     *
     * @param params   参数,多参数使用JSON数据
     */
    void run(String params);
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/TestTask.java
对比新文件
@@ -0,0 +1,22 @@
package com.iailab.module.shasteel.job.task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
 * 测试定时任务(演示Demo,可删除)
 *
 * testTask为spring bean的名称
 *
 * @author Mark sunlightcs@gmail.com
 */
@Component("testTask")
public class TestTask implements ITask{
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public void run(String params){
        logger.debug("TestTask定时任务正在执行,参数为:{}", params);
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleJob.java
对比新文件
@@ -0,0 +1,80 @@
package com.iailab.module.shasteel.job.utils;
import com.iailab.framework.common.constant.Constant;
import com.iailab.framework.common.exception.ExceptionUtils;
import com.iailab.framework.common.util.spring.SpringContextUtils;
import com.iailab.framework.tenant.core.context.TenantContextHolder;
import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
import com.iailab.module.shasteel.job.service.ScheduleJobLogService;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;
import java.util.Date;
/**
 * 定时任务
 *
 * @author Mark sunlightcs@gmail.com
 */
@DisallowConcurrentExecution
public class ScheduleJob extends QuartzJobBean {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    protected void executeInternal(JobExecutionContext context) {
        ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap().
                get(ScheduleUtils.JOB_PARAM_KEY);
        //设置当前租户
        TenantContextHolder.setTenantId(scheduleJob.getTenantId());
        Long tenantId = TenantContextHolder.getRequiredTenantId();
        //数据库保存执行记录
        ScheduleJobLogEntity log = new ScheduleJobLogEntity();
        log.setId(System.currentTimeMillis());
        log.setJobId(scheduleJob.getId());
        log.setBeanName(scheduleJob.getBeanName());
        log.setParams(scheduleJob.getParams());
        log.setCreateDate(new Date());
        log.setTenantId(tenantId);
        //任务开始时间
        long startTime = System.currentTimeMillis();
        try {
            //执行任务
            logger.info("任务准备执行,任务ID:{}", scheduleJob.getId());
            Object target = SpringContextUtils.getBean(scheduleJob.getBeanName());
            Method method = target.getClass().getDeclaredMethod("run", String.class);
            method.invoke(target, scheduleJob.getParams());
            //任务执行总时长
            long times = System.currentTimeMillis() - startTime;
            log.setTimes((int)times);
            //任务状态
            log.setStatus(Constant.SUCCESS);
            logger.info("任务执行完毕,任务ID:{}  总共耗时:{} 毫秒", scheduleJob.getId(), times);
        } catch (Exception e) {
            logger.error("任务执行失败,任务ID:{}", scheduleJob.getId(), e);
            //任务执行总时长
            long times = System.currentTimeMillis() - startTime;
            log.setTimes((int)times);
            //任务状态
            log.setStatus(Constant.FAIL);
            log.setError(ExceptionUtils.getErrorStackTrace(e));
        }finally {
            //获取spring bean
            ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean(ScheduleJobLogService.class);
            scheduleJobLogService.insert(log);
        }
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleUtils.java
对比新文件
@@ -0,0 +1,153 @@
package com.iailab.module.shasteel.job.utils;
import com.iailab.framework.common.constant.Constant;
import com.iailab.framework.common.enums.ErrorCode;
import com.iailab.framework.common.exception.ServerException;
import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
import org.quartz.*;
/**
 * 定时任务工具类
 *
 * @author Mark sunlightcs@gmail.com
 */
public class ScheduleUtils {
    private final static String JOB_NAME = "TASK_";
    /**
     * 任务调度参数key
     */
    public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
    /**
     * 获取触发器key
     */
    public static TriggerKey getTriggerKey(Long jobId) {
        return TriggerKey.triggerKey(JOB_NAME + jobId);
    }
    /**
     * 获取jobKey
     */
    public static JobKey getJobKey(Long jobId) {
        return JobKey.jobKey(JOB_NAME + jobId);
    }
    /**
     * 获取表达式触发器
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
        }
    }
    /**
     * 创建定时任务
     */
    public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getId())).build();
            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getId())).withSchedule(scheduleBuilder).build();
            //放入参数,运行时的方法可以获取
            jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
            scheduler.scheduleJob(jobDetail, trigger);
            //暂停任务
            if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
                pauseJob(scheduler, scheduleJob.getId());
            }
        } catch (SchedulerException e) {
            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
        }
    }
    /**
     * 更新定时任务
     */
    public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            TriggerKey triggerKey = getTriggerKey(scheduleJob.getId());
            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getId());
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            //参数
            trigger.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
            scheduler.rescheduleJob(triggerKey, trigger);
            //暂停任务
            if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
                pauseJob(scheduler, scheduleJob.getId());
            }
        } catch (SchedulerException e) {
            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
        }
    }
    /**
     * 立即执行任务
     */
    public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
        try {
            //参数
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(JOB_PARAM_KEY, scheduleJob);
            scheduler.triggerJob(getJobKey(scheduleJob.getId()), dataMap);
        } catch (SchedulerException e) {
            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
        }
    }
    /**
     * 暂停任务
     */
    public static void pauseJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.pauseJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
        }
    }
    /**
     * 恢复任务
     */
    public static void resumeJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.resumeJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
        }
    }
    /**
     * 删除定时任务
     */
    public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.deleteJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
        }
    }
}
shasteel-biz/src/main/java/com/iailab/module/shasteel/job/vo/ScheduleJobReqVO.java
对比新文件
@@ -0,0 +1,23 @@
package com.iailab.module.shasteel.job.vo;
import com.iailab.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
 * @author PanZhibao
 * @Description
 * @createTime 2024年08月23日
 */
@Schema(description = "数据平台 - 定时任务分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ScheduleJobReqVO extends PageParam {
    private String beanName;
    private Long tenantId;
}
shasteel-biz/src/main/resources/application.yaml
@@ -138,6 +138,20 @@
      url:  # Admin 管理后台 UI 的地址
  tenant: # 多租户相关配置项
    enable: true
    ignore-tables:
      - qrtz_blob_triggers
      - qrtz_calendars
      - qrtz_cron_triggers
      - qrtz_fired_triggers
      - qrtz_job_details
      - qrtz_locks
      - qrtz_paused_trigger_grps
      - qrtz_scheduler_state
      - qrtz_simple_triggers
      - qrtz_simprop_triggers
      - qrtz_triggers
      - schedule_job
      - schedule_job_log
  swagger:
    title: 沙钢智慧能源后台
    description: 提供管理员管理的所有功能
shasteel-biz/src/main/resources/mapper/job/ScheduleJobDao.xml
对比新文件
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.iailab.module.shasteel.job.dao.ScheduleJobDao">
    <!-- 批量更新状态 -->
    <update id="updateBatch">
        update schedule_job set status = #{status} where id in
        <foreach item="id" collection="ids"  open="(" separator="," close=")">
            #{id}
        </foreach>
    </update>
</mapper>
shasteel-biz/src/main/resources/mapper/job/ScheduleJobLogDao.xml
对比新文件
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.iailab.module.shasteel.job.dao.ScheduleJobLogDao">
</mapper>