| | |
| | | <artifactId>tencentcloud-sdk-java-sms</artifactId> <!-- 短信(腾讯云) --> |
| | | </dependency> |
| | | |
| | | |
| | | <dependency> |
| | | <groupId>org.quartz-scheduler</groupId> |
| | | <artifactId>quartz</artifactId> |
| | | <version>2.3.2</version> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | <build> |
对比新文件 |
| | |
| | | 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; |
| | | } |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.shasteel.job.controller.admin; |
| | | |
| | | 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.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("/shasteel/job/schedule") |
| | | @Tag(name = "定时任务") |
| | | public class ScheduleJobController { |
| | | @Resource |
| | | private ScheduleJobService scheduleJobService; |
| | | |
| | | @GetMapping("page") |
| | | @Operation(summary = "分页") |
| | | @PreAuthorize("@ss.hasPermission('shasteel: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('shasteel: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('shasteel: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('shasteel: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('shasteel: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(); |
| | | } |
| | | |
| | | } |
对比新文件 |
| | |
| | | /** |
| | | * 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); |
| | | } |
| | | } |
对比新文件 |
| | |
| | | package com.iailab.module.shasteel.job.controller; |
对比新文件 |
| | |
| | | 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); |
| | | } |
对比新文件 |
| | |
| | | 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> { |
| | | |
| | | } |
对比新文件 |
| | |
| | | /** |
| | | * 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; |
| | | |
| | | } |
对比新文件 |
| | |
| | | /** |
| | | * 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; |
| | | |
| | | } |
对比新文件 |
| | |
| | | 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; |
| | | } |
对比新文件 |
| | |
| | | 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; |
| | | |
| | | } |
对比新文件 |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | /** |
| | | * 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); |
| | | } |
对比新文件 |
| | |
| | | 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); |
| | | } |
对比新文件 |
| | |
| | | /** |
| | | * 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); |
| | | } |
| | | |
| | | } |
对比新文件 |
| | |
| | | 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()); |
| | | } |
| | | |
| | | } |
对比新文件 |
| | |
| | | /** |
| | | * 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); |
| | | } |
对比新文件 |
| | |
| | | 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); |
| | | } |
| | | } |
对比新文件 |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | 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()); |
| | | } |
| | | } |
| | | } |
对比新文件 |
| | |
| | | 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; |
| | | } |
| | |
| | | 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: 提供管理员管理的所有功能 |
对比新文件 |
| | |
| | | <?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> |
对比新文件 |
| | |
| | | <?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> |